git subrepo commit (merge) mailcow/src/mailcow-dockerized
subrepo: subdir: "mailcow/src/mailcow-dockerized"
merged: "02ae5285"
upstream: origin: "https://github.com/mailcow/mailcow-dockerized.git"
branch: "master"
commit: "649a5c01"
git-subrepo: version: "0.4.3"
origin: "???"
commit: "???"
Change-Id: I870ad468fba026cc5abf3c5699ed1e12ff28b32b
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/ajax/dns_diagnostics.php b/mailcow/src/mailcow-dockerized/data/web/inc/ajax/dns_diagnostics.php
index 928a4e4..a315680 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/ajax/dns_diagnostics.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/ajax/dns_diagnostics.php
@@ -2,479 +2,456 @@
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/spf.inc.php';
-define('state_good', '<span class="glyphicon glyphicon-ok text-success"></span>');
-define('state_missing', '<span class="glyphicon glyphicon-remove text-danger"></span>');
+define('state_good', '<i class="bi bi-check-lg text-success"></i>');
+define('state_missing', '<i class="bi bi-x-lg text-danger"></i>');
define('state_nomatch', "?");
define('state_optional', " <sup>2</sup>");
if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "admin"|| $_SESSION['mailcow_cc_role'] == "domainadmin")) {
-$domains = mailbox('get', 'domains');
-$alias_domains = array();
-foreach($domains as $dn) {
- $alias_domains = array_merge($alias_domains, mailbox('get', 'alias_domains', $dn));
-}
-$domains = array_merge($domains, $alias_domains);
+ $alias_domains = array();
-if (isset($_GET['domain'])) {
- if (is_valid_domain_name($_GET['domain'])) {
- if (in_array($_GET['domain'], $domains)) {
+ if (isset($_GET['domain'])) {
+ $domain_details = mailbox('get', 'domain_details', $_GET['domain']);
+ if ($domain_details !== false) {
$domain = $_GET['domain'];
+ $alias_domains = array_merge($alias_domains, mailbox('get', 'alias_domains', $domain));
}
else {
echo "No such domain in context";
exit();
}
}
- else {
- echo "Invalid domain name";
- exit();
- }
-}
-$ch = curl_init('http://ip4.mailcow.email');
-curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
-curl_setopt($ch, CURLOPT_VERBOSE, false);
-curl_setopt($ch, CURLOPT_HEADER, false);
-curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
-$ip = curl_exec($ch);
-curl_close($ch);
+ $ch = curl_init('http://ip4.mailcow.email');
+ curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
+ curl_setopt($ch, CURLOPT_VERBOSE, false);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
+ $ip = curl_exec($ch);
+ curl_close($ch);
-$ch = curl_init('http://ip6.mailcow.email');
-curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
-curl_setopt($ch, CURLOPT_VERBOSE, false);
-curl_setopt($ch, CURLOPT_HEADER, false);
-curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
-$ip6 = curl_exec($ch);
-curl_close($ch);
+ $ch = curl_init('http://ip6.mailcow.email');
+ curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
+ curl_setopt($ch, CURLOPT_VERBOSE, false);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
+ $ip6 = curl_exec($ch);
+ curl_close($ch);
-$ptr = implode('.', array_reverse(explode('.', $ip))) . '.in-addr.arpa';
-if (!empty($ip6)) {
- $ip6_full = str_replace('::', str_repeat(':', 9-substr_count($ip6, ':')), $ip6);
- $ip6_full = str_replace('::', ':0:', $ip6_full);
- $ip6_full = str_replace('::', ':0:', $ip6_full);
- $ptr6 = '';
- foreach (explode(':', $ip6_full) as $part) {
- $ptr6 .= str_pad($part, 4, '0', STR_PAD_LEFT);
- }
- $ptr6 = implode('.', array_reverse(str_split($ptr6, 1))) . '.ip6.arpa';
-}
-
-$https_port = strpos($_SERVER['HTTP_HOST'], ':');
-if ($https_port === FALSE) {
- $https_port = 443;
-}
-else {
- $https_port = substr($_SERVER['HTTP_HOST'], $https_port+1);
-}
-
-if (!isset($autodiscover_config['sieve'])) {
- $autodiscover_config['sieve'] = array('server' => $mailcow_hostname, 'port' => array_pop(explode(':', getenv('SIEVE_PORT'))));
-}
-
-// Init records array
-$spf_link = '<a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework" target="_blank">SPF Record Syntax</a><br />';
-$dmarc_link = '<a href="https://www.kitterman.com/dmarc/assistant.html" target="_blank">DMARC Assistant</a>';
-
-$records = array();
-if ($_SESSION['mailcow_cc_role'] == "admin") {
- $records[] = array(
- $mailcow_hostname,
- 'A',
- $ip
- );
- $records[] = array(
- $ptr,
- 'PTR',
- $mailcow_hostname
- );
+ $ptr = implode('.', array_reverse(explode('.', $ip))) . '.in-addr.arpa';
if (!empty($ip6)) {
+ $ip6_full = str_replace('::', str_repeat(':', 9-substr_count($ip6, ':')), $ip6);
+ $ip6_full = str_replace('::', ':0:', $ip6_full);
+ $ip6_full = str_replace('::', ':0:', $ip6_full);
+ $ptr6 = '';
+ foreach (explode(':', $ip6_full) as $part) {
+ $ptr6 .= str_pad($part, 4, '0', STR_PAD_LEFT);
+ }
+ $ptr6 = implode('.', array_reverse(str_split($ptr6, 1))) . '.ip6.arpa';
+ }
+
+ $https_port = strpos($_SERVER['HTTP_HOST'], ':');
+ if ($https_port === FALSE) {
+ $https_port = 443;
+ }
+ else {
+ $https_port = substr($_SERVER['HTTP_HOST'], $https_port+1);
+ }
+
+ if (!isset($autodiscover_config['sieve'])) {
+ $autodiscover_config['sieve'] = array(
+ 'server' => $mailcow_hostname,
+ 'port' => array_pop(explode(':', getenv('SIEVE_PORT')))
+ );
+ }
+
+ // Init records array
+ $spf_link = '<a href="http://www.open-spf.org/SPF_Record_Syntax/" target="_blank">SPF Record Syntax</a><br />';
+ $dmarc_link = '<a href="https://www.kitterman.com/dmarc/assistant.html" target="_blank">DMARC Assistant</a>';
+
+ $records = array();
+
+ if ($_SESSION['mailcow_cc_role'] == "admin") {
$records[] = array(
$mailcow_hostname,
- 'AAAA',
- expand_ipv6($ip6)
+ 'A',
+ $ip
);
$records[] = array(
- $ptr6,
+ $ptr,
'PTR',
$mailcow_hostname
);
+ if (!empty($ip6)) {
+ $records[] = array(
+ $mailcow_hostname,
+ 'AAAA',
+ expand_ipv6($ip6)
+ );
+ $records[] = array(
+ $ptr6,
+ 'PTR',
+ $mailcow_hostname
+ );
+ }
+ $records[] = array(
+ '_25._tcp.' . $autodiscover_config['smtp']['server'],
+ 'TLSA',
+ generate_tlsa_digest($autodiscover_config['smtp']['server'], 25, 1)
+ );
}
+
$records[] = array(
- '_25._tcp.'.$autodiscover_config['smtp']['server'],
- 'TLSA',
- generate_tlsa_digest($autodiscover_config['smtp']['server'], 25, 1)
+ $domain,
+ 'MX',
+ $mailcow_hostname
);
+
if (!in_array($domain, $alias_domains)) {
$records[] = array(
- '_'.$https_port.
- '._tcp.'.$mailcow_hostname,
- 'TLSA',
- generate_tlsa_digest($mailcow_hostname, $https_port)
+ 'autodiscover.' . $domain,
+ 'CNAME',
+ $mailcow_hostname
);
$records[] = array(
- '_'.$autodiscover_config['pop3']['tlsport'].
- '._tcp.'.$autodiscover_config['pop3']['server'],
- 'TLSA',
- generate_tlsa_digest($autodiscover_config['pop3']['server'], $autodiscover_config['pop3']['tlsport'], 1)
+ '_autodiscover._tcp.' . $domain,
+ 'SRV',
+ $mailcow_hostname . ' ' . $https_port
);
$records[] = array(
- '_'.$autodiscover_config['imap']['tlsport'].
- '._tcp.'.$autodiscover_config['imap']['server'],
- 'TLSA',
- generate_tlsa_digest($autodiscover_config['imap']['server'], $autodiscover_config['imap']['tlsport'], 1)
- );
- $records[] = array(
- '_'.$autodiscover_config['smtp']['port'].
- '._tcp.'.$autodiscover_config['smtp']['server'],
- 'TLSA',
- generate_tlsa_digest($autodiscover_config['smtp']['server'], $autodiscover_config['smtp']['port'])
- );
- $records[] = array(
- '_'.$autodiscover_config['smtp']['tlsport'].
- '._tcp.'.$autodiscover_config['smtp']['server'],
- 'TLSA',
- generate_tlsa_digest($autodiscover_config['smtp']['server'], $autodiscover_config['smtp']['tlsport'], 1)
- );
- $records[] = array(
- '_'.$autodiscover_config['imap']['port'].
- '._tcp.'.$autodiscover_config['imap']['server'],
- 'TLSA',
- generate_tlsa_digest($autodiscover_config['imap']['server'], $autodiscover_config['imap']['port'])
- );
- $records[] = array(
- '_'.$autodiscover_config['pop3']['port'].
- '._tcp.'.$autodiscover_config['pop3']['server'],
- 'TLSA',
- generate_tlsa_digest($autodiscover_config['pop3']['server'], $autodiscover_config['pop3']['port'])
- );
- $records[] = array(
- '_'.$autodiscover_config['sieve']['port'].
- '._tcp.'.$autodiscover_config['sieve']['server'],
- 'TLSA',
- generate_tlsa_digest($autodiscover_config['sieve']['server'], $autodiscover_config['sieve']['port'], 1)
+ 'autoconfig.' . $domain,
+ 'CNAME',
+ $mailcow_hostname
);
}
-}
-$records[] = array(
- $domain,
- 'MX',
- $mailcow_hostname
-);
-if (!in_array($domain, $alias_domains)) {
- $records[] = array(
- 'autodiscover.'.$domain,
- 'CNAME',
- $mailcow_hostname
- );
- $records[] = array(
- '_autodiscover._tcp.'.$domain,
- 'SRV',
- $mailcow_hostname.
- ' '.$https_port
- );
- $records[] = array(
- 'autoconfig.'.$domain,
- 'CNAME',
- $mailcow_hostname
- );
-}
-$records[] = array(
- $domain,
- 'TXT',
- $spf_link,
- state_optional
-);
-$records[] = array(
- '_dmarc.'.$domain,
- 'TXT',
- $dmarc_link,
- state_optional
-);
-if (!empty($dkim = dkim('details', $domain))) {
$records[] = array(
- $dkim['dkim_selector'] . '._domainkey.' . $domain,
+ $domain,
'TXT',
- $dkim['dkim_txt']
+ $spf_link,
+ state_optional
);
-}
-if (!in_array($domain, $alias_domains)) {
- $current_records = dns_get_record('_pop3._tcp.' . $domain, DNS_SRV);
- if (count($current_records) == 0 || $current_records[0]['target'] != '') {
- if ($autodiscover_config['pop3']['tlsport'] != '110') {
- $records[] = array(
- '_pop3._tcp.' . $domain,
- 'SRV',
- $autodiscover_config['pop3']['server'] . ' ' . $autodiscover_config['pop3']['tlsport']
- );
- }
- }
- else {
- $records[] = array(
- '_pop3._tcp.' . $domain,
- 'SRV',
- '. 0'
- );
- }
- $current_records = dns_get_record('_pop3s._tcp.' . $domain, DNS_SRV);
- if (count($current_records) == 0 || $current_records[0]['target'] != '') {
- if ($autodiscover_config['pop3']['port'] != '995') {
- $records[] = array(
- '_pop3s._tcp.' . $domain,
- 'SRV',
- $autodiscover_config['pop3']['server'] . ' ' . $autodiscover_config['pop3']['port']
- );
- }
- }
- else {
- $records[] = array(
- '_pop3s._tcp.' . $domain,
- 'SRV',
- '. 0'
- );
- }
- if ($autodiscover_config['imap']['tlsport'] != '143') {
- $records[] = array(
- '_imap._tcp.' . $domain,
- 'SRV',
- $autodiscover_config['imap']['server'] . ' ' . $autodiscover_config['imap']['tlsport']
- );
- }
- if ($autodiscover_config['imap']['port'] != '993') {
- $records[] = array(
- '_imaps._tcp.' . $domain,
- 'SRV',
- $autodiscover_config['imap']['server'] . ' ' . $autodiscover_config['imap']['port']
- );
- }
- if ($autodiscover_config['smtp']['tlsport'] != '587') {
- $records[] = array(
- '_submission._tcp.' . $domain,
- 'SRV',
- $autodiscover_config['smtp']['server'] . ' ' . $autodiscover_config['smtp']['tlsport']
- );
- }
- if ($autodiscover_config['smtp']['port'] != '465') {
- $records[] = array(
- '_smtps._tcp.' . $domain,
- 'SRV',
- $autodiscover_config['smtp']['server'] . ' ' . $autodiscover_config['smtp']['port']
- );
- }
- if ($autodiscover_config['sieve']['port'] != '4190') {
- $records[] = array(
- '_sieve._tcp.' . $domain,
- 'SRV',
- $autodiscover_config['sieve']['server'] . ' ' . $autodiscover_config['sieve']['port']
- );
- }
-}
-$record_types = array(
- 'A' => DNS_A,
- 'AAAA' => DNS_AAAA,
- 'CNAME' => DNS_CNAME,
- 'MX' => DNS_MX,
- 'PTR' => DNS_PTR,
- 'SRV' => DNS_SRV,
- 'TXT' => DNS_TXT,
-);
-$data_field = array(
- 'A' => 'ip',
- 'AAAA' => 'ipv6',
- 'CNAME' => 'target',
- 'MX' => 'target',
- 'PTR' => 'target',
- 'SRV' => 'data',
- 'TLSA' => 'data',
- 'TXT' => 'txt',
-);
+ $records[] = array(
+ '_dmarc.' . $domain,
+ 'TXT',
+ $dmarc_link,
+ state_optional
+ );
-?>
-<div class="table-responsive" id="dnstable">
- <table class="table table-striped">
- <tr>
- <th><?=$lang['diagnostics']['dns_records_name'];?></th>
- <th><?=$lang['diagnostics']['dns_records_type'];?></th>
- <th><?=$lang['diagnostics']['dns_records_data'];?></th>
- <th><?=$lang['diagnostics']['dns_records_status'];?></th>
- </tr>
-<?php
-foreach ($records as &$record) {
- $record[1] = strtoupper($record[1]);
- $state = state_missing;
- if ($record[1] == 'TLSA') {
- $currents = dns_get_record($record[0], 52, $_, $_, TRUE);
- foreach ($currents as &$current) {
- $current['type'] = 'TLSA';
- $current['cert_usage'] = hexdec(bin2hex($current['data']{0}));
- $current['selector'] = hexdec(bin2hex($current['data']{1}));
- $current['match_type'] = hexdec(bin2hex($current['data']{2}));
- $current['cert_data'] = bin2hex(substr($current['data'], 3));
- $current['data'] = $current['cert_usage'] . ' ' . $current['selector'] . ' ' . $current['match_type'] . ' ' . $current['cert_data'];
- }
- unset($current);
- }
- else {
- $currents = dns_get_record($record[0], $record_types[$record[1]]);
- if ($record[0] == $mailcow_hostname && ($record[1] == "A" || $record[1] == "AAAA")) {
- if (!empty(dns_get_record($record[0], DNS_CNAME))) {
- $currents[0]['ip'] = state_missing . ' <b>(CNAME)</b>';
- $currents[0]['ipv6'] = state_missing . ' <b>(CNAME)</b>';
- }
- }
- if ($record[1] == 'SRV') {
- foreach ($currents as &$current) {
- if ($current['target'] == '') {
- $current['target'] = '.';
- $current['port'] = '0';
- }
- $current['data'] = $current['target'] . ' ' . $current['port'];
- }
- unset($current);
- }
- elseif ($record[1] == 'TXT') {
- foreach ($currents as &$current) {
- unset($current);
- }
- unset($current);
- }
- elseif ($record[1] == 'AAAA') {
- foreach ($currents as &$current) {
- $current['ipv6'] = expand_ipv6($current['ipv6']);
- }
- }
+ if (!empty($dkim = dkim('details', $domain))) {
+ $records[] = array(
+ $dkim['dkim_selector'] . '._domainkey.' . $domain,
+ 'TXT',
+ $dkim['dkim_txt']
+ );
}
- if ($record[1] == 'CNAME' && count($currents) == 0) {
- // A and AAAA are also valid instead of CNAME
- $a = dns_get_record($record[0], DNS_A);
- $cname = dns_get_record($record[2], DNS_A);
- if (count($a) > 0 && count($cname) > 0) {
- if ($a[0]['ip'] == $cname[0]['ip']) {
- $currents = array(array('host' => $record[0], 'class' => 'IN', 'type' => 'CNAME', 'target' => $record[2]));
- $aaaa = dns_get_record($record[0], DNS_AAAA);
- $cname = dns_get_record($record[2], DNS_AAAA);
- if (count($aaaa) == 0 || count($cname) == 0 || expand_ipv6($aaaa[0]['ipv6']) != expand_ipv6($cname[0]['ipv6'])) {
- $currents[0]['target'] = expand_ipv6($aaaa[0]['ipv6']) . ' <sup>1</sup>';
- }
- }
- else {
- $currents = array(array('host' => $record[0], 'class' => 'IN', 'type' => 'CNAME', 'target' => $a[0]['ip'] . ' <sup>1</sup>'));
- }
- }
- }
-
- foreach ($currents as &$current) {
- if ($current['type'] == 'TXT' &&
- stripos($current['txt'], 'v=dmarc') === 0 &&
- $record[2] == $dmarc_link) {
- $current['txt'] = str_replace(' ', '', $current['txt']);
- $state = $current[$data_field[$current['type']]] . state_optional;
- }
- elseif ($current['type'] == 'TXT' &&
- stripos($current['txt'], 'v=spf') === 0 &&
- $record[2] == $spf_link) {
- $state = state_nomatch;
- $rslt = get_spf_allowed_hosts($record[0]);
- if(in_array($ip, $rslt) && in_array(expand_ipv6($ip6), $rslt)){
- $state = state_good;
- }
- $state .= '<br />' . $current[$data_field[$current['type']]].state_optional;
- }
- elseif ($current['type'] == 'TXT' &&
- stripos($current['txt'], 'v=dkim') === 0 &&
- stripos($record[2], 'v=dkim') === 0) {
- preg_match('/v=DKIM1;.*k=rsa;.*p=([^;]*).*/i', $current[$data_field[$current['type']]], $dkim_matches_current);
- preg_match('/v=DKIM1;.*k=rsa;.*p=([^;]*).*/i', $record[2], $dkim_matches_good);
- if ($dkim_matches_current[1] == $dkim_matches_good[1]) {
- $state = state_good;
- }
- }
- elseif ($current['type'] != 'TXT' &&
- isset($data_field[$current['type']]) && $state != state_good) {
- $state = state_nomatch;
- if ($current[$data_field[$current['type']]] == $record[2]) {
- $state = state_good;
- }
- }
- }
- unset($current);
-
- if (isset($record[3]) &&
- $record[3] == state_optional &&
- ($state == state_missing || $state == state_nomatch)) {
- $state = state_optional;
- }
-
- if ($state == state_nomatch) {
- $state = array();
- foreach ($currents as $current) {
- $state[] = $current[$data_field[$current['type']]];
- }
- $state = implode('<br />', $state);
- }
- echo sprintf('<tr>
- <td>%s</td>
- <td>%s</td>
- <td class="dns-found">%s</td>
- <td class="dns-recommended">%s</td>
- </tr>', $record[0], $record[1], $record[2], $state);
- $record[3] = explode('<br />', $state);
-}
-unset($record);
-
-$dns_data = sprintf("\$ORIGIN %s.\n", $domain);
-foreach ($records as $record) {
- if ($domain == substr($record[0], -strlen($domain))) {
- $label = substr($record[0], 0, -strlen($domain)-1);
- $val = $record[2];
- if (strlen($label) == 0) {
- $label = "@";
- }
- $vals = array();
- if (strpos($val, "<a") !== FALSE) {
- if(is_array($record[3]) && count($record[3]) == 1 && $record[3][0] == state_optional) {
- $record[3][0] = "**TODO**";
- $label = ';' . $label;
- }
- foreach ($record[3] as $val) {
- $val = str_replace(state_optional, '', $val);
- $val = str_replace(state_good, '', $val);
- if (strlen($val) > 0) {
- $vals[] = sprintf("%s\tIN\t%s\t%s\n", $label, $record[1], $val);
- }
+ if (!in_array($domain, $alias_domains)) {
+ $current_records = dns_get_record('_pop3._tcp.' . $domain, DNS_SRV);
+ if (count($current_records) == 0 || $current_records[0]['target'] != '') {
+ if ($autodiscover_config['pop3']['tlsport'] != '110') {
+ $records[] = array(
+ '_pop3._tcp.' . $domain,
+ 'SRV',
+ $autodiscover_config['pop3']['server'] . ' ' . $autodiscover_config['pop3']['tlsport']
+ );
}
}
else {
- $vals[] = sprintf("%s\tIN\t%s\t%s\n", $label, $record[1], $val);
+ $records[] = array(
+ '_pop3._tcp.' . $domain,
+ 'SRV',
+ '. 0'
+ );
}
- foreach ($vals as $val) {
- $dns_data .= str_replace($domain, $domain . '.', $val);
+
+ $current_records = dns_get_record('_pop3s._tcp.' . $domain, DNS_SRV);
+
+ if (count($current_records) == 0 || $current_records[0]['target'] != '') {
+ if ($autodiscover_config['pop3']['port'] != '995') {
+ $records[] = array(
+ '_pop3s._tcp.' . $domain,
+ 'SRV',
+ $autodiscover_config['pop3']['server'] . ' ' . $autodiscover_config['pop3']['port']
+ );
+ }
+ }
+ else {
+ $records[] = array(
+ '_pop3s._tcp.' . $domain,
+ 'SRV',
+ '. 0'
+ );
+ }
+
+ if ($autodiscover_config['imap']['tlsport'] != '143') {
+ $records[] = array(
+ '_imap._tcp.' . $domain,
+ 'SRV',
+ $autodiscover_config['imap']['server'] . ' ' . $autodiscover_config['imap']['tlsport']
+ );
+ }
+
+ if ($autodiscover_config['imap']['port'] != '993') {
+ $records[] = array(
+ '_imaps._tcp.' . $domain,
+ 'SRV',
+ $autodiscover_config['imap']['server'] . ' ' . $autodiscover_config['imap']['port']
+ );
+ }
+
+ if ($autodiscover_config['smtp']['tlsport'] != '587') {
+ $records[] = array(
+ '_submission._tcp.' . $domain,
+ 'SRV',
+ $autodiscover_config['smtp']['server'] . ' ' . $autodiscover_config['smtp']['tlsport']
+ );
+ }
+
+ if ($autodiscover_config['smtp']['port'] != '465') {
+ $records[] = array(
+ '_smtps._tcp.' . $domain,
+ 'SRV',
+ $autodiscover_config['smtp']['server'] . ' ' . $autodiscover_config['smtp']['port']
+ );
+ }
+
+ if ($autodiscover_config['sieve']['port'] != '4190') {
+ $records[] = array(
+ '_sieve._tcp.' . $domain,
+ 'SRV',
+ $autodiscover_config['sieve']['server'] . ' ' . $autodiscover_config['sieve']['port']
+ );
}
}
-}
-?>
- </table>
- <a id='download-zonefile' data-zonefile="<?=base64_encode($dns_data);?>" download='<?=$_GET['domain'];?>.txt' type='text/csv'>Download</a>
- <script>
+ $record_types = array(
+ 'A' => DNS_A,
+ 'AAAA' => DNS_AAAA,
+ 'CNAME' => DNS_CNAME,
+ 'MX' => DNS_MX,
+ 'PTR' => DNS_PTR,
+ 'SRV' => DNS_SRV,
+ 'TXT' => DNS_TXT,
+ );
+
+ $data_field = array(
+ 'A' => 'ip',
+ 'AAAA' => 'ipv6',
+ 'CNAME' => 'target',
+ 'MX' => 'target',
+ 'PTR' => 'target',
+ 'SRV' => 'data',
+ 'TLSA' => 'data',
+ 'TXT' => 'txt',
+ );
+
+ ?>
+ <div class="table-responsive" id="dnstable">
+ <table class="table table-striped">
+ <tr>
+ <th><?=$lang['diagnostics']['dns_records_name'];?></th>
+ <th><?=$lang['diagnostics']['dns_records_type'];?></th>
+ <th><?=$lang['diagnostics']['dns_records_data'];?></th>
+ <th><?=$lang['diagnostics']['dns_records_status'];?></th>
+ </tr>
+ <?php
+ foreach ($records as &$record) {
+ $record[1] = strtoupper($record[1]);
+ $state = state_optional;
+
+ if ($record[1] == 'TLSA') {
+ $currents = dns_get_record($record[0], 52, $_, $_, TRUE);
+ foreach ($currents as &$current) {
+ $current['type'] = 'TLSA';
+ $current['cert_usage'] = hexdec(bin2hex($current['data'][0]));
+ $current['selector'] = hexdec(bin2hex($current['data'][1]));
+ $current['match_type'] = hexdec(bin2hex($current['data'][2]));
+ $current['cert_data'] = bin2hex(substr($current['data'], 3));
+ $current['data'] = $current['cert_usage'] . ' ' . $current['selector'] . ' ' . $current['match_type'] . ' ' . $current['cert_data'];
+ }
+ unset($current);
+ }
+ else {
+ $currents = dns_get_record($record[0], $record_types[$record[1]]);
+ if ($record[0] == $mailcow_hostname && ($record[1] == "A" || $record[1] == "AAAA")) {
+ if (!empty(dns_get_record($record[0], DNS_CNAME))) {
+ $currents[0]['ip'] = state_missing . ' <b>(CNAME)</b>';
+ $currents[0]['ipv6'] = state_missing . ' <b>(CNAME)</b>';
+ }
+ }
+ if ($record[1] == 'SRV') {
+ foreach ($currents as &$current) {
+ if ($current['target'] == '') {
+ $current['target'] = '.';
+ $current['port'] = '0';
+ }
+ $current['data'] = $current['target'] . ' ' . $current['port'];
+ }
+ unset($current);
+ }
+ elseif ($record[1] == 'TXT') {
+ foreach ($currents as &$current) {
+ unset($current);
+ }
+ unset($current);
+ }
+ elseif ($record[1] == 'AAAA') {
+ foreach ($currents as &$current) {
+ $current['ipv6'] = expand_ipv6($current['ipv6']);
+ }
+ }
+ }
+
+ if ($record[1] == 'CNAME' && count($currents) == 0) {
+ // A and AAAA are also valid instead of CNAME
+ $a = dns_get_record($record[0], DNS_A);
+ $cname = dns_get_record($record[2], DNS_A);
+ if (count($a) > 0 && count($cname) > 0) {
+ if ($a[0]['ip'] == $cname[0]['ip']) {
+ $currents = array(
+ array(
+ 'host' => $record[0],
+ 'class' => 'IN',
+ 'type' => 'CNAME',
+ 'target' => $record[2]
+ )
+ );
+ $aaaa = dns_get_record($record[0], DNS_AAAA);
+ $cname = dns_get_record($record[2], DNS_AAAA);
+ if (count($aaaa) == 0 || count($cname) == 0 || expand_ipv6($aaaa[0]['ipv6']) != expand_ipv6($cname[0]['ipv6'])) {
+ $currents[0]['target'] = expand_ipv6($aaaa[0]['ipv6']) . ' <sup>1</sup>';
+ }
+ }
+ else {
+ $currents = array(
+ array(
+ 'host' => $record[0],
+ 'class' => 'IN',
+ 'type' => 'CNAME',
+ 'target' => $a[0]['ip'] . ' <sup>1</sup>'
+ )
+ );
+ }
+ }
+ }
+
+ foreach ($currents as &$current) {
+ if ($current['type'] == 'TXT' &&
+ stripos($current['txt'], 'v=dmarc') === 0 &&
+ $record[2] == $dmarc_link) {
+ $current['txt'] = str_replace(' ', '', $current['txt']);
+ $state = $current[$data_field[$current['type']]] . state_optional;
+ }
+ elseif ($current['type'] == 'TXT' &&
+ stripos($current['txt'], 'v=spf') === 0 &&
+ $record[2] == $spf_link) {
+ $state = state_nomatch;
+ $rslt = get_spf_allowed_hosts($record[0], true);
+ if (in_array($ip, $rslt) && in_array(expand_ipv6($ip6), $rslt)) {
+ $state = state_good;
+ }
+ $state .= '<br />' . $current[$data_field[$current['type']]] . state_optional;
+ }
+ elseif ($current['type'] == 'TXT' &&
+ stripos($current['txt'], 'v=dkim') === 0 &&
+ stripos($record[2], 'v=dkim') === 0) {
+ preg_match('/v=DKIM1;.*k=rsa;.*p=([^;]*).*/i', $current[$data_field[$current['type']]], $dkim_matches_current);
+ preg_match('/v=DKIM1;.*k=rsa;.*p=([^;]*).*/i', $record[2], $dkim_matches_good);
+ if ($dkim_matches_current[1] == $dkim_matches_good[1]) {
+ $state = state_good;
+ }
+ }
+ elseif ($current['type'] != 'TXT' &&
+ isset($data_field[$current['type']]) && $state != state_good) {
+ $state = state_nomatch;
+ if ($current[$data_field[$current['type']]] == $record[2]) {
+ $state = state_good;
+ }
+ }
+ }
+ unset($current);
+
+ if (isset($record[3]) &&
+ $record[3] == state_optional &&
+ ($state == state_missing || $state == state_nomatch)) {
+ $state = state_optional;
+ }
+
+ if ($state == state_nomatch) {
+ $state = array();
+ foreach ($currents as $current) {
+ $state[] = $current[$data_field[$current['type']]];
+ }
+ $state = implode('<br />', $state);
+ }
+ echo sprintf('
+ <tr>
+ <td>%s</td>
+ <td>%s</td>
+ <td class="dns-found">%s</td>
+ <td class="dns-recommended">%s</td>
+ </tr>', $record[0], $record[1], $record[2], $state);
+ $record[3] = explode('<br />', $state);
+ }
+
+ unset($record);
+
+ $dns_data = sprintf("\$ORIGIN %s.\n", $domain);
+ foreach ($records as $record) {
+ if ($domain == substr($record[0], -strlen($domain))) {
+ $label = substr($record[0], 0, -strlen($domain)-1);
+ $val = $record[2];
+
+ if (strlen($label) == 0) {
+ $label = "@";
+ }
+
+ $vals = array();
+ if (strpos($val, "<a") !== FALSE) {
+ if (is_array($record[3]) && count($record[3]) == 1 && $record[3][0] == state_optional) {
+ $record[3][0] = "**TODO**";
+ $label = ';' . $label;
+ }
+ foreach ($record[3] as $val) {
+ $val = str_replace(state_optional, '', $val);
+ $val = str_replace(state_good, '', $val);
+ if (strlen($val) > 0) {
+ $vals[] = sprintf("%s\tIN\t%s\t%s\n", $label, $record[1], $val);
+ }
+ }
+ }
+ else {
+ $vals[] = sprintf("%s\tIN\t%s\t%s\n", $label, $record[1], $val);
+ }
+
+ foreach ($vals as $val) {
+ $dns_data .= str_replace($domain, $domain . '.', $val);
+ }
+ }
+ }
+ ?>
+ </table>
+ <a id='download-zonefile' class="btn btn-sm btn-default visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline" style="margin-top:10px" data-zonefile="<?=base64_encode($dns_data);?>" download='<?=$_GET['domain'];?>.txt' type='text/csv'>Download</a>
+ <script>
var zonefile_dl_link = document.getElementById('download-zonefile');
var zonefile = atob(zonefile_dl_link.getAttribute('data-zonefile'));
var data = new Blob([zonefile]);
var download_zonefile_link = document.getElementById('download-zonefile');
download_zonefile_link.href = URL.createObjectURL(data);
- </script>
-</div>
-<p class="help-block">
-<sup>1</sup> <?=$lang['diagnostics']['cname_from_a'];?><br />
-<sup>2</sup> <?=$lang['diagnostics']['optional'];?>
-</p>
-<?php
-} else {
+ </script>
+ </div>
+ <p class="help-block">
+ <sup>1</sup> <?=$lang['diagnostics']['cname_from_a'];?><br />
+ <sup>2</sup> <?=$lang['diagnostics']['optional'];?>
+ </p>
+ <?php
+}
+else {
echo "Session invalid";
exit();
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/ajax/transport_check.php b/mailcow/src/mailcow-dockerized/data/web/inc/ajax/transport_check.php
index 7921687..aa429ed 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/ajax/transport_check.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/ajax/transport_check.php
@@ -15,6 +15,12 @@
else {
$mail_from = "relay@example.org";
}
+ if (isset($_GET['mail_rcpt']) && filter_var($_GET['mail_rcpt'], FILTER_VALIDATE_EMAIL)) {
+ $mail_rcpt = $_GET['mail_rcpt'];
+ }
+ else {
+ $mail_rcpt = "null@hosted.mailcow.de";
+ }
if ($transport_type == 'transport-map') {
$transport_details = transport('details', $transport_id);
$nexthop = $transport_details['nexthop'];
@@ -36,7 +42,7 @@
$port = substr($hostname_w_port, strrpos($hostname_w_port, ':') + 1);
$hostname = preg_replace('/'. preg_quote(':' . $port, '/') . '$/', '', $hostname_w_port);
if (filter_var($hostname, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
- $hostname = '[' . $hostname . ']:';
+ $hostname = '[' . $hostname . ']';
}
}
else {
@@ -130,7 +136,7 @@
$mail->Port = $port;
$mail->setFrom($mail_from, 'Mailer');
$mail->Subject = 'A subject for a SMTP test';
- $mail->addAddress($RELAY_TO, 'Joe Null');
+ $mail->addAddress($mail_rcpt, 'Joe Null');
$mail->Body = 'This is our test body';
$mail->send();
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/footer.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/footer.inc.php
index 8738cc6..f99c86d 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/footer.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/footer.inc.php
@@ -79,6 +79,7 @@
foreach($alertbox_log_parser as $log) {
$alerts[$log['type']][] = $log['msg'];
}
+ $alerts = array_filter(array_unique($alerts));
foreach($alerts as $alert_type => $alert_msg) {
?>
mailcow_alert_box(<?=json_encode(implode('<hr class="alert-hr">', $alert_msg));?>, <?=$alert_type;?>);
@@ -93,7 +94,7 @@
backdrop: 'static',
keyboard: false
});
- $('#u2f_status_auth').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> ' + lang_tfa.init_u2f + '</p>');
+ $('#u2f_status_auth').html('<p><i class="bi bi-arrow-repeat icon-spin"></i> ' + lang_tfa.init_u2f + '</p>');
$('#ConfirmTFAModal').on('shown.bs.modal', function(){
$(this).find('input[name=token]').focus();
// If U2F
@@ -235,7 +236,7 @@
$("#start_u2f_register").click(function(){
$('#u2f_return_code').html('');
$('#u2f_return_code').hide();
- $('#u2f_status_reg').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> ' + lang_tfa.init_u2f + '</p>');
+ $('#u2f_status_reg').html('<p><i class="bi bi-arrow-repeat icon-spin"></i> ' + lang_tfa.init_u2f + '</p>');
$.ajax({
type: "GET",
cache: false,
@@ -304,5 +305,12 @@
</body>
</html>
<?php
+if (isset($_SESSION['mailcow_cc_api'])) {
+ session_regenerate_id(true);
+ session_unset();
+ session_destroy();
+ session_write_close();
+ header("Location: /");
+}
$stmt = null;
$pdo = null;
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.address_rewriting.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.address_rewriting.inc.php
index 51cdd73..8193c05 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.address_rewriting.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.address_rewriting.inc.php
@@ -1,5 +1,5 @@
<?php
-function bcc($_action, $_data = null, $attr = null) {
+function bcc($_action, $_data = null, $_attr = null) {
global $pdo;
global $lang;
if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
@@ -48,7 +48,8 @@
$local_dest_sane = '@' . idn_to_ascii($local_dest, 0, INTL_IDNA_VARIANT_UTS46);
}
elseif (filter_var($local_dest, FILTER_VALIDATE_EMAIL)) {
- if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $local_dest)) {
+ $mailbox = mailbox('get', 'mailbox_details', $local_dest);
+ if ($mailbox === false && array_key_exists($local_dest, array_merge($direct_aliases, $shared_aliases)) === false) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
@@ -56,10 +57,16 @@
);
return false;
}
- $domain = mailbox('get', 'mailbox_details', $local_dest)['domain'];
- if (empty($domain)) {
- return false;
+ if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $local_dest) &&
+ !hasAliasObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $local_dest)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
+ 'msg' => 'access_denied'
+ );
+ return false;
}
+ $domain = idn_to_ascii(substr(strstr($local_dest, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
$local_dest_sane = $local_dest;
}
else {
@@ -128,7 +135,6 @@
);
continue;
}
- $active = intval($_data['active']);
if (!filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) {
$_SESSION['return'][] = array(
'type' => 'danger',
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.admin.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.admin.inc.php
index bb0400e..af1474c 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.admin.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.admin.inc.php
@@ -48,40 +48,17 @@
return false;
}
}
- if (!empty($password) && !empty($password2)) {
- if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_complexity'
- );
- return false;
- }
- if ($password != $password2) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_mismatch'
- );
- return false;
- }
- $password_hashed = hash_password($password);
- $stmt = $pdo->prepare("INSERT INTO `admin` (`username`, `password`, `superadmin`, `active`)
- VALUES (:username, :password_hashed, '1', :active)");
- $stmt->execute(array(
- ':username' => $username,
- ':password_hashed' => $password_hashed,
- ':active' => $active
- ));
- }
- else {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_empty'
- );
+ if (password_check($password, $password2) !== true) {
return false;
}
+ $password_hashed = hash_password($password_new);
+ $stmt = $pdo->prepare("INSERT INTO `admin` (`username`, `password`, `superadmin`, `active`)
+ VALUES (:username, :password_hashed, '1', :active)");
+ $stmt->execute(array(
+ ':username' => $username,
+ ':password_hashed' => $password_hashed,
+ ':active' => $active
+ ));
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
@@ -144,22 +121,9 @@
continue;
}
}
- if (!empty($password) && !empty($password2)) {
- if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_complexity'
- );
- continue;
- }
- if ($password != $password2) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_mismatch'
- );
- continue;
+ if (!empty($password)) {
+ if (password_check($password, $password2) !== true) {
+ return false;
}
$password_hashed = hash_password($password);
$stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.app_passwd.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.app_passwd.inc.php
index c4b0026..8c8ad18 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.app_passwd.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.app_passwd.inc.php
@@ -23,9 +23,9 @@
}
switch ($_action) {
case 'add':
- $app_name = trim($_data['app_name']);
- $password = $_data['app_passwd'];
- $password2 = $_data['app_passwd2'];
+ $app_name = htmlspecialchars(trim($_data['app_name']));
+ $password = $_data['app_passwd'];
+ $password2 = $_data['app_passwd2'];
$active = intval($_data['active']);
$domain = mailbox('get', 'mailbox_details', $username)['domain'];
if (empty($domain)) {
@@ -94,7 +94,7 @@
);
continue;
}
- $app_name = trim($app_name);
+ $app_name = htmlspecialchars(trim($app_name));
if (!empty($password) && !empty($password2)) {
if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
$_SESSION['return'][] = array(
@@ -198,6 +198,7 @@
$app_passwd_data = array();
return false;
}
+ $app_passwd_data['name'] = htmlspecialchars(trim($app_passwd_data['name']));
return $app_passwd_data;
break;
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.customize.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.customize.inc.php
index f4c74d8..d594822 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.customize.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.customize.inc.php
@@ -207,7 +207,7 @@
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['apps_name'] = ($apps_name = $redis->get('APPS_NAME')) ? $apps_name : $lang['header']['apps'];
$data['help_text'] = ($help_text = $redis->get('HELP_TEXT')) ? $help_text : false;
if (!empty($redis->get('UI_IMPRESS'))) {
$redis->set('UI_FOOTER', $redis->get('UI_IMPRESS'));
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.dkim.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.dkim.inc.php
index 2a19ff0..33ee49f 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.dkim.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.dkim.inc.php
@@ -1,8 +1,8 @@
<?php
function dkim($_action, $_data = null, $privkey = false) {
- global $redis;
- global $lang;
+ global $redis;
+ global $lang;
switch ($_action) {
case 'add':
if ($_SESSION['mailcow_cc_role'] != "admin") {
@@ -13,7 +13,7 @@
);
return false;
}
- $key_length = intval($_data['key_size']);
+ $key_length = intval($_data['key_size']);
$dkim_selector = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : 'dkim';
$domains = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['domains']));
$domains = array_filter($domains);
@@ -21,7 +21,7 @@
if (!is_valid_domain_name($domain) || !is_numeric($key_length)) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_domain_or_sel_invalid', $domain)
);
continue;
@@ -29,7 +29,7 @@
if ($redis->hGet('DKIM_PUB_KEYS', $domain)) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_domain_or_sel_invalid', $domain)
);
continue;
@@ -37,7 +37,7 @@
if (!ctype_alnum(str_replace(['-', '_'], '', $dkim_selector))) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_domain_or_sel_invalid', $domain)
);
continue;
@@ -62,7 +62,7 @@
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('redis_error', $e)
);
continue;
@@ -76,7 +76,7 @@
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('redis_error', $e)
);
continue;
@@ -84,14 +84,14 @@
}
$_SESSION['return'][] = array(
'type' => 'success',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_added', $domain)
);
}
else {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_domain_or_sel_invalid', $domain)
);
continue;
@@ -102,7 +102,7 @@
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => 'access_denied'
);
return false;
@@ -112,7 +112,7 @@
if (empty($from_domain_dkim)) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_domain_or_sel_invalid', $from_domain)
);
continue;
@@ -128,14 +128,14 @@
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('redis_error', $e)
);
continue;
}
$_SESSION['return'][] = array(
'type' => 'success',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_duplicated', $from_domain, $to_domain)
);
}
@@ -144,7 +144,7 @@
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => 'access_denied'
);
return false;
@@ -156,7 +156,7 @@
if ($ssl_error = openssl_error_string()) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('private_key_error', $ssl_error)
);
return false;
@@ -167,13 +167,13 @@
array_shift($pem_public_key_array);
array_pop($pem_public_key_array);
// Implode as single string
- $pem_public_key = implode('', $pem_public_key_array);
+ $pem_public_key = implode('', (array)$pem_public_key_array);
$dkim_selector = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : 'dkim';
- $domain = $_data['domain'];
+ $domain = $_data['domain'];
if (!is_valid_domain_name($domain)) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_domain_or_sel_invalid', $domain)
);
return false;
@@ -182,7 +182,7 @@
if ($overwrite_existing == 0) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_domain_or_sel_exists', $domain)
);
return false;
@@ -191,13 +191,13 @@
if (!ctype_alnum($dkim_selector)) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_domain_or_sel_invalid', $domain)
);
return false;
}
try {
- dkim('delete', $domain);
+ dkim('delete', (array)$domain);
$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);
@@ -205,7 +205,7 @@
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('redis_error', $e)
);
return false;
@@ -218,14 +218,14 @@
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('redis_error', $e)
);
return false;
}
$_SESSION['return'][] = array(
'type' => 'success',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_added', $domain)
);
return true;
@@ -251,7 +251,7 @@
}
if ($GLOBALS['SPLIT_DKIM_255'] === true) {
$dkim_txt_tmp = str_split('v=DKIM1;k=rsa;t=s;s=email;p=' . $redis_dkim_key_data, 255);
- $dkimdata['dkim_txt'] = sprintf('"%s"', implode('" "', $dkim_txt_tmp ) );
+ $dkimdata['dkim_txt'] = sprintf('"%s"', implode('" "', (array)$dkim_txt_tmp ) );
}
else {
$dkimdata['dkim_txt'] = 'v=DKIM1;k=rsa;t=s;s=email;p=' . $redis_dkim_key_data;
@@ -270,7 +270,7 @@
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => 'access_denied'
);
return false;
@@ -286,7 +286,7 @@
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => 'access_denied'
);
return false;
@@ -295,7 +295,7 @@
if (!is_valid_domain_name($domain)) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_domain_or_sel_invalid', $domain)
);
continue;
@@ -309,14 +309,14 @@
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('redis_error', $e)
);
continue;
}
$_SESSION['return'][] = array(
'type' => 'success',
- 'log' => array(__FUNCTION__, $_action, $_data, $privkey),
+ 'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('dkim_removed', htmlspecialchars($domain))
);
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.domain_admin.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.domain_admin.inc.php
index 206b371..804c0f8 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.domain_admin.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.domain_admin.inc.php
@@ -65,61 +65,38 @@
return false;
}
}
- if (!empty($password) && !empty($password2)) {
- if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_complexity'
- );
- return false;
- }
- if ($password != $password2) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_mismatch'
- );
- return false;
- }
- $password_hashed = hash_password($password);
- $valid_domains = 0;
- foreach ($domains as $domain) {
- if (!is_valid_domain_name($domain) || mailbox('get', 'domain_details', $domain) === false) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => array('domain_invalid', htmlspecialchars($domain))
- );
- continue;
- }
- $valid_domains++;
- $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
- ));
- }
- if ($valid_domains != 0) {
- $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
- ));
- }
+ if (password_check($password, $password2) !== true) {
+ continue;
}
- else {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_empty'
- );
- return false;
+ $password_hashed = hash_password($password);
+ $valid_domains = 0;
+ foreach ($domains as $domain) {
+ if (!is_valid_domain_name($domain) || mailbox('get', 'domain_details', $domain) === false) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => array('domain_invalid', htmlspecialchars($domain))
+ );
+ continue;
+ }
+ $valid_domains++;
+ $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
+ ));
+ }
+ if ($valid_domains != 0) {
+ $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
+ ));
}
$stmt = $pdo->prepare("INSERT INTO `da_acl` (`username`) VALUES (:username)");
$stmt->execute(array(
@@ -218,22 +195,9 @@
));
}
}
- if (!empty($password) && !empty($password2)) {
- if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_complexity'
- );
- continue;
- }
- if ($password != $password2) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_mismatch'
- );
- continue;
+ if (!empty($password)) {
+ if (password_check($password, $password2) !== true) {
+ return false;
}
$password_hashed = hash_password($password);
$stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
@@ -296,30 +260,15 @@
);
return false;
}
- if (!empty($password_new2) && !empty($password_new)) {
- if ($password_new2 != $password_new) {
- $_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(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => 'password_complexity'
- );
- return false;
- }
- $password_hashed = hash_password($password_new);
- $stmt = $pdo->prepare("UPDATE `admin` SET `password` = :password_hashed WHERE `username` = :username");
- $stmt->execute(array(
- ':password_hashed' => $password_hashed,
- ':username' => $username
- ));
+ if (password_check($password_new, $password_new2) !== true) {
+ return false;
}
+ $password_hashed = hash_password($password_new);
+ $stmt = $pdo->prepare("UPDATE `admin` SET `password` = :password_hashed WHERE `username` = :username");
+ $stmt->execute(array(
+ ':password_hashed' => $password_hashed,
+ ':username' => $username
+ ));
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.fail2ban.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.fail2ban.inc.php
index 6f6b024..2a7f11e 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.fail2ban.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.fail2ban.inc.php
@@ -18,7 +18,7 @@
}
if (isset($tmp_wl_data)) {
natsort($tmp_wl_data);
- $f2b_options['whitelist'] = implode(PHP_EOL, $tmp_wl_data);
+ $f2b_options['whitelist'] = implode(PHP_EOL, (array)$tmp_wl_data);
}
else {
$f2b_options['whitelist'] = "";
@@ -34,7 +34,7 @@
}
if (isset($tmp_bl_data)) {
natsort($tmp_bl_data);
- $f2b_options['blacklist'] = implode(PHP_EOL, $tmp_bl_data);
+ $f2b_options['blacklist'] = implode(PHP_EOL, (array)$tmp_bl_data);
}
else {
$f2b_options['blacklist'] = "";
@@ -46,7 +46,11 @@
$pb = $redis->hGetAll('F2B_PERM_BANS');
if (is_array($pb)) {
foreach ($pb as $key => $value) {
- $f2b_options['perm_bans'][] = $key;
+ $f2b_options['perm_bans'][] = array(
+ 'network'=>$key,
+ 'ip' => strtok($key,'/')
+ );
+
}
}
else {
@@ -61,6 +65,7 @@
$f2b_options['active_bans'][] = array(
'queued_for_unban' => $queued_for_unban,
'network' => $network,
+ 'ip' => strtok($network,'/'),
'banned_until' => sprintf('%02dh %02dm %02ds', ($difference/3600), ($difference/60%60), $difference%60)
);
}
@@ -133,14 +138,6 @@
$redis->Set('F2B_REGEX', json_encode($regex_array, JSON_UNESCAPED_SLASHES));
}
}
- else {
- $_SESSION['return'][] = array(
- 'type' => 'success',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => print_r($_data, true)
- );
- return false;
- }
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.fwdhost.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.fwdhost.inc.php
index 5c511f4..d7ac256 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.fwdhost.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.fwdhost.inc.php
@@ -1,8 +1,8 @@
<?php
function fwdhost($_action, $_data = null) {
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/spf.inc.php';
- global $redis;
- global $lang;
+ global $redis;
+ global $lang;
$_data_log = $_data;
switch ($_action) {
case 'add':
@@ -57,7 +57,7 @@
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => array('forwarding_host_added', htmlspecialchars(implode(', ', $hosts)))
+ 'msg' => array('forwarding_host_added', htmlspecialchars(implode(', ', (array)$hosts)))
);
break;
case 'edit':
@@ -180,4 +180,4 @@
return $fwdhostdetails;
break;
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.inc.php
index e3f2882..142a9fe 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.inc.php
@@ -13,6 +13,17 @@
return false;
}
}
+function readable_random_string($length = 8) {
+ $string = '';
+ $vowels = array('a', 'e', 'i', 'o', 'u');
+ $consonants = array('b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z');
+ $max = $length / 2;
+ for ($i = 1; $i <= $max; $i++) {
+ $string .= $consonants[rand(0,19)];
+ $string .= $vowels[rand(0,4)];
+ }
+ return $string;
+}
// Validates ips and cidrs
function valid_network($network) {
if (filter_var($network, FILTER_VALIDATE_IP)) {
@@ -88,40 +99,253 @@
// in case default pass scheme is not defined, falling back to BLF-CRYPT.
global $default_pass_scheme;
$pw_hash = NULL;
- switch (strtoupper($default_pass_scheme)) {
- case "SSHA":
- $salt_str = bin2hex(openssl_random_pseudo_bytes(8));
- $pw_hash = "{SSHA}".base64_encode(hash('sha1', $password . $salt_str, true) . $salt_str);
- break;
- case "SSHA256":
- $salt_str = bin2hex(openssl_random_pseudo_bytes(8));
- $pw_hash = "{SSHA256}".base64_encode(hash('sha256', $password . $salt_str, true) . $salt_str);
- break;
- case "SSHA512":
- $salt_str = bin2hex(openssl_random_pseudo_bytes(8));
- $pw_hash = "{SSHA512}".base64_encode(hash('sha512', $password . $salt_str, true) . $salt_str);
- break;
- case "BLF-CRYPT":
- default:
- $pw_hash = "{BLF-CRYPT}" . password_hash($password, PASSWORD_BCRYPT);
- break;
+ // support pre-hashed passwords
+ if (preg_match('/^{(ARGON2I|ARGON2ID|BLF-CRYPT|CLEAR|CLEARTEXT|CRYPT|DES-CRYPT|LDAP-MD5|MD5|MD5-CRYPT|PBKDF2|PLAIN|PLAIN-MD4|PLAIN-MD5|PLAIN-TRUNC|PLAIN-TRUNC|SHA|SHA1|SHA256|SHA256-CRYPT|SHA512|SHA512-CRYPT|SMD5|SSHA|SSHA256|SSHA512)}/i', $password)) {
+ $pw_hash = $password;
+ }
+ else {
+ switch (strtoupper($default_pass_scheme)) {
+ case "SSHA":
+ $salt_str = bin2hex(openssl_random_pseudo_bytes(8));
+ $pw_hash = "{SSHA}".base64_encode(hash('sha1', $password . $salt_str, true) . $salt_str);
+ break;
+ case "SSHA256":
+ $salt_str = bin2hex(openssl_random_pseudo_bytes(8));
+ $pw_hash = "{SSHA256}".base64_encode(hash('sha256', $password . $salt_str, true) . $salt_str);
+ break;
+ case "SSHA512":
+ $salt_str = bin2hex(openssl_random_pseudo_bytes(8));
+ $pw_hash = "{SSHA512}".base64_encode(hash('sha512', $password . $salt_str, true) . $salt_str);
+ break;
+ case "BLF-CRYPT":
+ default:
+ $pw_hash = "{BLF-CRYPT}" . password_hash($password, PASSWORD_BCRYPT);
+ break;
+ }
}
return $pw_hash;
}
-function last_login($user) {
- global $pdo;
- $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;
+function password_complexity($_action, $_data = null) {
+ global $redis;
+ global $lang;
+ switch ($_action) {
+ case 'edit':
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ $is_now = password_complexity('get');
+ if (!empty($is_now)) {
+ $length = (isset($_data['length']) && intval($_data['length']) >= 3) ? intval($_data['length']) : $is_now['length'];
+ $chars = (isset($_data['chars'])) ? intval($_data['chars']) : $is_now['chars'];
+ $lowerupper = (isset($_data['lowerupper'])) ? intval($_data['lowerupper']) : $is_now['lowerupper'];
+ $special_chars = (isset($_data['special_chars'])) ? intval($_data['special_chars']) : $is_now['special_chars'];
+ $numbers = (isset($_data['numbers'])) ? intval($_data['numbers']) : $is_now['numbers'];
+ }
+ try {
+ $redis->hMSet('PASSWD_POLICY', [
+ 'length' => $length,
+ 'chars' => $chars,
+ 'special_chars' => $special_chars,
+ 'lowerupper' => $lowerupper,
+ 'numbers' => $numbers
+ ]);
+ }
+ catch (RedisException $e) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data),
+ 'msg' => array('redis_error', $e)
+ );
+ return false;
+ }
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
+ 'log' => array(__FUNCTION__, $_action, $_data),
+ 'msg' => 'password_policy_saved'
+ );
+ break;
+ case 'get':
+ try {
+ $length = $redis->hGet('PASSWD_POLICY', 'length');
+ $chars = $redis->hGet('PASSWD_POLICY', 'chars');
+ $special_chars = $redis->hGet('PASSWD_POLICY', 'special_chars');
+ $lowerupper = $redis->hGet('PASSWD_POLICY', 'lowerupper');
+ $numbers = $redis->hGet('PASSWD_POLICY', 'numbers');
+ return array(
+ 'length' => $length,
+ 'chars' => $chars,
+ 'special_chars' => $special_chars,
+ 'lowerupper' => $lowerupper,
+ 'numbers' => $numbers
+ );
+ }
+ catch (RedisException $e) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data),
+ 'msg' => array('redis_error', $e)
+ );
+ return false;
+ }
+ return false;
+ break;
+ case 'html':
+ $policies = password_complexity('get');
+ foreach ($policies as $name => $value) {
+ if ($value != 0) {
+ $policy_text[] = sprintf($lang['admin']["password_policy_$name"], $value);
+ }
+ }
+ return '<p class="help-block small">- ' . implode('<br>- ', (array)$policy_text) . '</p>';
+ break;
}
- else {
+}
+function password_check($password1, $password2) {
+ $password_complexity = password_complexity('get');
+
+ if (empty($password1) || empty($password2)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type),
+ 'msg' => 'password_complexity'
+ );
return false;
}
+
+ if ($password1 != $password2) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type),
+ 'msg' => 'password_mismatch'
+ );
+ return false;
+ }
+
+ $given_password['length'] = strlen($password1);
+ $given_password['special_chars'] = preg_match('/[^a-zA-Z\d]/', $password1);
+ $given_password['chars'] = preg_match('/[a-zA-Z]/',$password1);
+ $given_password['numbers'] = preg_match('/\d/', $password1);
+ $lower = strlen(preg_replace("/[^a-z]/", '', $password1));
+ $upper = strlen(preg_replace("/[^A-Z]/", '', $password1));
+ $given_password['lowerupper'] = ($lower > 0 && $upper > 0) ? true : false;
+
+ if (
+ ($given_password['length'] < $password_complexity['length']) ||
+ ($password_complexity['special_chars'] == 1 && (intval($given_password['special_chars']) != $password_complexity['special_chars'])) ||
+ ($password_complexity['chars'] == 1 && (intval($given_password['chars']) != $password_complexity['chars'])) ||
+ ($password_complexity['numbers'] == 1 && (intval($given_password['numbers']) != $password_complexity['numbers'])) ||
+ ($password_complexity['lowerupper'] == 1 && (intval($given_password['lowerupper']) != $password_complexity['lowerupper']))
+ ) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type),
+ 'msg' => 'password_complexity'
+ );
+ return false;
+ }
+
+ return true;
+}
+function last_login($action, $username, $sasl_limit_days = 7) {
+ global $pdo;
+ global $redis;
+ $sasl_limit_days = intval($sasl_limit_days);
+ switch ($action) {
+ case 'get':
+ if (filter_var($username, FILTER_VALIDATE_EMAIL) && hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
+ $stmt = $pdo->prepare('SELECT `real_rip`, MAX(`datetime`) as `datetime`, `service`, `app_password` FROM `sasl_log`
+ LEFT OUTER JOIN `app_passwd` on `sasl_log`.`app_password` = `app_passwd`.`id`
+ WHERE `username` = :username
+ AND HOUR(TIMEDIFF(NOW(), `datetime`)) < :sasl_limit_days
+ GROUP BY `real_rip`, `service`, `app_password`
+ ORDER BY `datetime` DESC;');
+ $stmt->execute(array(':username' => $username, ':sasl_limit_days' => ($sasl_limit_days * 24)));
+ $sasl = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ foreach ($sasl as $k => $v) {
+ if (!filter_var($sasl[$k]['real_rip'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
+ $sasl[$k]['real_rip'] = 'Web/EAS/Internal (' . $sasl[$k]['real_rip'] . ')';
+ }
+ elseif (filter_var($sasl[$k]['real_rip'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
+ try {
+ $sasl[$k]['location'] = $redis->hGet('IP_SHORTCOUNTRY', $sasl[$k]['real_rip']);
+ }
+ catch (RedisException $e) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => array('redis_error', $e)
+ );
+ return false;
+ }
+ if (!$sasl[$k]['location']) {
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_URL,"https://dfdata.bella.network/lookup/" . $sasl[$k]['real_rip']);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_USERAGENT, 'Moocow');
+ curl_setopt($curl, CURLOPT_TIMEOUT, 5);
+ $ip_data = curl_exec($curl);
+ if (!curl_errno($curl)) {
+ $ip_data_array = json_decode($ip_data, true);
+ if ($ip_data_array !== false and !empty($ip_data_array['location']['shortcountry'])) {
+ $sasl[$k]['location'] = $ip_data_array['location']['shortcountry'];
+ try {
+ $redis->hSet('IP_SHORTCOUNTRY', $sasl[$k]['real_rip'], $ip_data_array['location']['shortcountry']);
+ }
+ catch (RedisException $e) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => array('redis_error', $e)
+ );
+ curl_close($curl);
+ return false;
+ }
+ }
+ }
+ curl_close($curl);
+ }
+ }
+ }
+ }
+ else {
+ $sasl = array();
+ }
+ if ($_SESSION['mailcow_cc_role'] == "admin" || $username == $_SESSION['mailcow_cc_username']) {
+ $stmt = $pdo->prepare('SELECT `remote`, `time` FROM `logs`
+ WHERE JSON_EXTRACT(`call`, "$[0]") = "check_login"
+ AND JSON_EXTRACT(`call`, "$[1]") = :username
+ AND `type` = "success" ORDER BY `time` DESC LIMIT 1 OFFSET 1');
+ $stmt->execute(array(':username' => $username));
+ $ui = $stmt->fetch(PDO::FETCH_ASSOC);
+ }
+ else {
+ $ui = array();
+ }
+
+ return array('ui' => $ui, 'sasl' => $sasl);
+ break;
+ case 'reset':
+ if (filter_var($username, FILTER_VALIDATE_EMAIL) && hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
+ $stmt = $pdo->prepare('DELETE FROM `sasl_log`
+ WHERE `username` = :username');
+ $stmt->execute(array(':username' => $username));
+ }
+ if ($_SESSION['mailcow_cc_role'] == "admin" || $username == $_SESSION['mailcow_cc_username']) {
+ $stmt = $pdo->prepare('DELETE FROM `logs`
+ WHERE JSON_EXTRACT(`call`, "$[0]") = "check_login"
+ AND JSON_EXTRACT(`call`, "$[1]") = :username
+ AND `type` = "success"');
+ $stmt->execute(array(':username' => $username));
+ }
+ return true;
+ break;
+ }
+
}
function flush_memcached() {
try {
@@ -135,13 +359,13 @@
}
function sys_mail($_data) {
if ($_SESSION['mailcow_cc_role'] != "admin") {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__),
- 'msg' => 'access_denied'
- );
- return false;
- }
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
$excludes = $_data['mass_exclude'];
$includes = $_data['mass_include'];
$mailboxes = array();
@@ -150,28 +374,28 @@
$mass_html = $_data['mass_html'];
$mass_subject = $_data['mass_subject'];
if (!filter_var($mass_from, FILTER_VALIDATE_EMAIL)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__),
- 'msg' => 'from_invalid'
- );
- return false;
+ 'msg' => 'from_invalid'
+ );
+ return false;
}
if (empty($mass_subject)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__),
- 'msg' => 'subject_empty'
- );
- return false;
+ 'msg' => 'subject_empty'
+ );
+ return false;
}
if (empty($mass_text)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__),
- 'msg' => 'text_empty'
- );
- return false;
+ 'msg' => 'text_empty'
+ );
+ return false;
}
$domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
foreach ($domains as $domain) {
@@ -265,8 +489,14 @@
$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);
+ $msg = null;
+ if (isset($return['msg'])) {
+ $msg = json_encode($return['msg'], JSON_UNESCAPED_UNICODE);
+ }
+ $call = null;
+ if (isset($return['log'])) {
+ $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'];
@@ -303,16 +533,16 @@
}
}
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') {
- return false;
- }
+ 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') {
+ return false;
+ }
if ($role == 'admin') {
$stmt = $pdo->prepare("SELECT `domain` FROM `domain`
WHERE `domain` = :domain");
@@ -339,48 +569,49 @@
return true;
}
}
- return false;
+ return false;
}
function hasMailboxObjectAccess($username, $role, $object) {
- global $pdo;
- if (empty($username) || empty($role) || empty($object)) {
- return false;
- }
- 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;
- }
+ global $pdo;
+ if (empty($username) || empty($role) || empty($object)) {
+ return false;
+ }
+ 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;
+ }
$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;
+ return false;
}
+// does also verify mailboxes as a mailbox is a alias == goto
function hasAliasObjectAccess($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;
- }
+ global $pdo;
+ if (empty($username) || empty($role) || empty($object)) {
+ return false;
+ }
+ 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;
+ }
$stmt = $pdo->prepare("SELECT `domain` FROM `alias` WHERE `address` = :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;
+ return false;
}
function pem_to_der($pem_key) {
// Need to remove BEGIN/END PUBLIC KEY
@@ -390,9 +621,9 @@
return base64_decode(implode('', $lines));
}
function expand_ipv6($ip) {
- $hex = unpack("H*hex", inet_pton($ip));
- $ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1);
- return $ip;
+ $hex = unpack("H*hex", inet_pton($ip));
+ $ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1);
+ return $ip;
}
function generate_tlsa_digest($hostname, $port, $starttls = null) {
if (!is_valid_domain_name($hostname)) {
@@ -453,15 +684,20 @@
return 'Error: Cannot read peer certificate';
}
}
-function alertbox_log_parser($_data){
+function alertbox_log_parser($_data) {
global $lang;
if (isset($_data['return'])) {
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 (isset($return['type']) && isset($return['msg']) && !is_array($return['msg'])) {
+ if (isset($lang[$return['type']][$return['msg']])) {
+ $msg = $lang[$return['type']][$return['msg']];
+ }
+ else {
+ $msg = $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'])) {
@@ -471,9 +707,8 @@
$return['msg']
);
}
- // If none applies, use msg as returned message
else {
- $msg = $return['msg'];
+ $msg = '-';
}
$log_array[] = array('msg' => $msg, 'type' => json_encode($type));
}
@@ -483,100 +718,116 @@
}
return false;
}
+function verify_salted_hash($hash, $password, $algo, $salt_length) {
+ // Decode hash
+ $dhash = base64_decode($hash);
+ // Get first n bytes of binary which equals a SSHA hash
+ $ohash = substr($dhash, 0, $salt_length);
+ // Remove SSHA hash from decoded hash to get original salt string
+ $osalt = str_replace($ohash, '', $dhash);
+ // Check single salted SSHA hash against extracted hash
+ if (hash_equals(hash($algo, $password . $osalt, true), $ohash)) {
+ return true;
+ }
+ 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('/^{SSHA}/i', $hash)) {
- // Remove tag if any
- $hash = preg_replace('/^{SSHA}/i', '', $hash);
- // Decode hash
- $dhash = base64_decode($hash);
- // Get first 20 bytes of binary which equals a SSHA hash
- $ohash = substr($dhash, 0, 20);
- // Remove SSHA hash from decoded hash to get original salt string
- $osalt = str_replace($ohash, '', $dhash);
- // Check single salted SSHA hash against extracted hash
- if (hash_equals(hash('sha1', $password . $osalt, true), $ohash)) {
- return true;
- }
- }
- elseif (preg_match('/^{PLAIN-MD5}/i', $hash)) {
- $hash = preg_replace('/^{PLAIN-MD5}/i', '', $hash);
- if (md5($password) == $hash) {
- 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;
- }
- }
- elseif (preg_match('/^{MD5-CRYPT}/i', $hash)) {
- $hash = preg_replace('/^{MD5-CRYPT}/i', '', $hash);
- if (password_verify($password, $hash)) {
- return true;
- }
- }
- elseif (preg_match('/^{BLF-CRYPT}/i', $hash)) {
- $hash = preg_replace('/^{BLF-CRYPT}/i', '', $hash);
- if (password_verify($password, $hash)) {
- return true;
+ if (preg_match('/^{(.+)}(.+)/i', $hash, $hash_array)) {
+ $scheme = strtoupper($hash_array[1]);
+ $hash = $hash_array[2];
+ switch ($scheme) {
+ case "ARGON2I":
+ case "ARGON2ID":
+ case "BLF-CRYPT":
+ case "CRYPT":
+ case "DES-CRYPT":
+ case "MD5-CRYPT":
+ case "MD5":
+ case "SHA256-CRYPT":
+ case "SHA512-CRYPT":
+ return password_verify($password, $hash);
+
+ case "CLEAR":
+ case "CLEARTEXT":
+ case "PLAIN":
+ return $password == $hash;
+
+ case "LDAP-MD5":
+ $hash = base64_decode($hash);
+ return hash_equals(hash('md5', $password, true), $hash);
+
+ case "PBKDF2":
+ $components = explode('$', $hash);
+ $salt = $components[2];
+ $rounds = $components[3];
+ $hash = $components[4];
+ return hash_equals(hash_pbkdf2('sha1', $password, $salt, $rounds), $hash);
+
+ case "PLAIN-MD4":
+ return hash_equals(hash('md4', $password), $hash);
+
+ case "PLAIN-MD5":
+ return md5($password) == $hash;
+
+ case "PLAIN-TRUNC":
+ $components = explode('-', $hash);
+ if (count($components) > 1) {
+ $trunc_len = $components[0];
+ $trunc_password = $components[1];
+
+ return substr($password, 0, $trunc_len) == $trunc_password;
+ } else {
+ return $password == $hash;
+ }
+
+ case "SHA":
+ case "SHA1":
+ case "SHA256":
+ case "SHA512":
+ // SHA is an alias for SHA1
+ $scheme = $scheme == "SHA" ? "sha1" : strtolower($scheme);
+ $hash = base64_decode($hash);
+ return hash_equals(hash($scheme, $password, true), $hash);
+
+ case "SMD5":
+ return verify_salted_hash($hash, $password, 'md5', 16);
+
+ case "SSHA":
+ return verify_salted_hash($hash, $password, 'sha1', 20);
+
+ case "SSHA256":
+ return verify_salted_hash($hash, $password, 'sha256', 32);
+
+ case "SSHA512":
+ return verify_salted_hash($hash, $password, 'sha512', 64);
+
+ default:
+ return false;
}
}
return false;
}
function check_login($user, $pass) {
- global $pdo;
- global $redis;
- global $imap_server;
- if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
+ global $pdo;
+ global $redis;
+ global $imap_server;
+ if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
$_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 `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)) {
+ return false;
+ }
+ $user = strtolower(trim($user));
+ $stmt = $pdo->prepare("SELECT `password` FROM `admin`
+ WHERE `superadmin` = '1'
+ 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)) {
if (get_tfa($user)['name'] != "none") {
$_SESSION['pending_mailcow_cc_username'] = $user;
$_SESSION['pending_mailcow_cc_role'] = "admin";
@@ -601,16 +852,16 @@
);
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) {
+ }
+ }
+ $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";
@@ -635,55 +886,55 @@
);
return "domainadmin";
}
- }
- }
- $stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
+ }
+ }
+ $stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
INNER JOIN domain on mailbox.domain = domain.domain
- WHERE `kind` NOT REGEXP 'location|thing|group'
+ WHERE `kind` NOT REGEXP 'location|thing|group'
AND `mailbox`.`active`='1'
AND `domain`.`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']);
+ $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(
'type' => 'success',
'log' => array(__FUNCTION__, $user, '*'),
'msg' => array('logged_in_as', $user)
);
- return "user";
- }
- }
- if (!isset($_SESSION['ldelay'])) {
- $_SESSION['ldelay'] = "0";
+ 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;
+ }
+ 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']);
- }
+ error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
+ }
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $user, '*'),
'msg' => 'login_failed'
);
- sleep($_SESSION['ldelay']);
+ sleep($_SESSION['ldelay']);
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)];
+ 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 update_sogo_static_view() {
if (getenv('SKIP_SOGO') == "y") {
@@ -702,15 +953,15 @@
flush_memcached();
}
function edit_user_account($_data) {
- global $lang;
- global $pdo;
+ 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'];
+ $password_old = $_data['user_old_pass'];
if (filter_var($username, FILTER_VALIDATE_EMAIL === false) || $role != 'user') {
$_SESSION['return'][] = array(
'type' => 'danger',
@@ -719,15 +970,11 @@
);
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'
+ $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);
+ $stmt->execute(array(':user' => $username));
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!verify_hash($row['password'], $password_old)) {
$_SESSION['return'][] = array(
'type' => 'danger',
@@ -736,59 +983,43 @@
);
return false;
}
- if (isset($password_new) && isset($password_new2)) {
- if (!empty($password_new2) && !empty($password_new)) {
- if ($password_new2 != $password_new) {
- $_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(
- '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(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_data_log),
- 'msg' => array('mysql_error', $e)
- );
- return false;
- }
- }
- }
+ if (!empty($_data['user_new_pass']) && !empty($_data['user_new_pass2'])) {
+ $password_new = $_data['user_new_pass'];
+ $password_new2 = $_data['user_new_pass2'];
+ if (password_check($password_new, $password_new2) !== true) {
+ return false;
+ }
+ $password_hashed = hash_password($password_new);
+ $stmt = $pdo->prepare("UPDATE `mailbox` SET `password` = :password_hashed,
+ `attributes` = JSON_SET(`attributes`, '$.force_pw_update', '0'),
+ `attributes` = JSON_SET(`attributes`, '$.passwd_update', NOW())
+ WHERE `username` = :username");
+ $stmt->execute(array(
+ ':password_hashed' => $password_hashed,
+ ':username' => $username
+ ));
+ }
update_sogo_static_view();
- $_SESSION['return'][] = array(
- 'type' => 'success',
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
'log' => array(__FUNCTION__, $_data_log),
- 'msg' => array('mailbox_modified', htmlspecialchars($username))
- );
+ 'msg' => array('mailbox_modified', htmlspecialchars($username))
+ );
}
function user_get_alias_details($username) {
- global $pdo;
- $data['direct_aliases'] = false;
- $data['shared_aliases'] = false;
+ global $pdo;
+ global $lang;
+ $data['direct_aliases'] = array();
+ $data['shared_aliases'] = array();
if ($_SESSION['mailcow_cc_role'] == "user") {
- $username = $_SESSION['mailcow_cc_username'];
+ $username = $_SESSION['mailcow_cc_username'];
}
if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
return false;
}
+ if (!hasMailboxObjectAccess($username, $_SESSION['mailcow_cc_role'], $username)) {
+ return false;
+ }
$data['address'] = $username;
$stmt = $pdo->prepare("SELECT `address` AS `shared_aliases`, `public_comment` FROM `alias`
WHERE `goto` REGEXP :username_goto
@@ -803,7 +1034,6 @@
$run = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($run)) {
$data['shared_aliases'][$row['shared_aliases']]['public_comment'] = htmlspecialchars($row['public_comment']);
-
//$data['shared_aliases'][] = $row['shared_aliases'];
}
@@ -829,21 +1059,22 @@
if (empty($row['ad_alias'])) {
continue;
}
- $data['direct_aliases'][$row['ad_alias']]['public_comment'] = '↪ ' . $row['alias_domain'];
+ $data['direct_aliases'][$row['ad_alias']]['public_comment'] = $lang['add']['alias_domain'];
+ $data['alias_domains'][] = $row['alias_domain'];
}
- $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '✘') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :username AND `send_as` NOT LIKE '@%';");
+ $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :username AND `send_as` NOT LIKE '@%';");
$stmt->execute(array(':username' => $username));
$run = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($run)) {
$data['aliases_also_send_as'] = $row['send_as'];
}
- $stmt = $pdo->prepare("SELECT CONCAT_WS(', ', IFNULL(GROUP_CONCAT(DISTINCT `send_as` SEPARATOR ', '), '✘'), GROUP_CONCAT(DISTINCT CONCAT('@',`alias_domain`) SEPARATOR ', ')) AS `send_as` FROM `sender_acl` LEFT JOIN `alias_domain` ON `alias_domain`.`target_domain` = TRIM(LEADING '@' FROM `send_as`) WHERE `logged_in_as` = :username AND `send_as` LIKE '@%';");
+ $stmt = $pdo->prepare("SELECT CONCAT_WS(', ', IFNULL(GROUP_CONCAT(DISTINCT `send_as` SEPARATOR ', '), ''), GROUP_CONCAT(DISTINCT CONCAT('@',`alias_domain`) SEPARATOR ', ')) AS `send_as` FROM `sender_acl` LEFT JOIN `alias_domain` ON `alias_domain`.`target_domain` = TRIM(LEADING '@' FROM `send_as`) WHERE `logged_in_as` = :username AND `send_as` LIKE '@%';");
$stmt->execute(array(':username' => $username));
$run = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($run)) {
$data['aliases_send_as_all'] = $row['send_as'];
}
- $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '✘') as `address` FROM `alias` WHERE `goto` REGEXP :username AND `address` LIKE '@%';");
+ $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '') as `address` FROM `alias` WHERE `goto` REGEXP :username AND `address` LIKE '@%';");
$stmt->execute(array(':username' => '(^|,)'.$username.'($|,)'));
$run = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($run)) {
@@ -852,24 +1083,23 @@
return $data;
}
function is_valid_domain_name($domain_name) {
- if (empty($domain_name)) {
- return false;
- }
- $domain_name = idn_to_ascii($domain_name, 0, INTL_IDNA_VARIANT_UTS46);
- return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name)
- && preg_match("/^.{1,253}$/", $domain_name)
- && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name));
+ if (empty($domain_name)) {
+ return false;
+ }
+ $domain_name = idn_to_ascii($domain_name, 0, INTL_IDNA_VARIANT_UTS46);
+ return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name)
+ && preg_match("/^.{1,253}$/", $domain_name)
+ && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name));
}
function set_tfa($_data) {
- global $pdo;
- global $yubi;
- global $u2f;
- global $tfa;
+ 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") {
+ if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
@@ -878,20 +1108,37 @@
return false;
}
$stmt = $pdo->prepare("SELECT `password` FROM `admin`
- WHERE `username` = :user");
- $stmt->execute(array(':user' => $username));
+ WHERE `username` = :username");
+ $stmt->execute(array(':username' => $username));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
- if (!verify_hash($row['password'], $_data["confirm_password"])) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_data_log),
- 'msg' => 'access_denied'
- );
- return false;
+ $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
+ if (!empty($num_results)) {
+ if (!verify_hash($row['password'], $_data["confirm_password"])) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_data_log),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
}
-
- switch ($_data["tfa_method"]) {
- case "yubi_otp":
+ $stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
+ WHERE `username` = :username");
+ $stmt->execute(array(':username' => $username));
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
+ if (!empty($num_results)) {
+ if (!verify_hash($row['password'], $_data["confirm_password"])) {
+ $_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'];
@@ -904,55 +1151,55 @@
);
return false;
}
- if (!ctype_alnum($_data["otp_token"]) || strlen($_data["otp_token"]) != 44) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ if (!ctype_alnum($_data["otp_token"]) || strlen($_data["otp_token"]) != 44) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
- 'msg' => 'tfa_token_invalid'
- );
- return false;
- }
+ 'msg' => 'tfa_token_invalid'
+ );
+ return false;
+ }
$yauth = $yubi->verify($_data["otp_token"]);
if (PEAR::isError($yauth)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => array('yotp_verification_failed', $yauth->getMessage())
- );
- return false;
+ );
+ return false;
}
- try {
+ 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(
- 'type' => 'danger',
+ $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(
+ 'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
- 'msg' => array('mysql_error', $e)
- );
- return false;
- }
- $_SESSION['return'][] = array(
- 'type' => 'success',
+ 'msg' => array('mysql_error', $e)
+ );
+ return false;
+ }
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
'log' => array(__FUNCTION__, $_data_log),
- 'msg' => array('object_modified', htmlspecialchars($username))
- );
- break;
- case "u2f":
+ '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->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(
@@ -971,8 +1218,8 @@
$_SESSION['regReq'] = null;
return false;
}
- break;
- case "totp":
+ break;
+ case "totp":
$key_id = (!isset($_data["key_id"])) ? 'unidentified' : $_data["key_id"];
if ($tfa->verifyCode($_POST['totp_secret'], $_POST['totp_confirm_token']) === true) {
$stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
@@ -992,28 +1239,27 @@
'msg' => 'totp_verification_failed'
);
}
- break;
- case "none":
+ break;
+ case "none":
$stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
- $_SESSION['return'][] = array(
- 'type' => 'success',
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
'log' => array(__FUNCTION__, $_data_log),
- 'msg' => array('object_modified', htmlspecialchars($username))
- );
- break;
- }
+ 'msg' => array('object_modified', htmlspecialchars($username))
+ );
+ break;
+ }
}
function fido2($_data) {
- global $pdo;
+ global $pdo;
$_data_log = $_data;
// Not logging registration data, only actions
// Silent errors for "get" requests
- switch ($_data["action"]) {
- case "register":
+ switch ($_data["action"]) {
+ case "register":
$username = $_SESSION['mailcow_cc_username'];
- if ($_SESSION['mailcow_cc_role'] != "domainadmin" &&
- $_SESSION['mailcow_cc_role'] != "admin") {
+ if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data["action"]),
@@ -1040,13 +1286,12 @@
'log' => array(__FUNCTION__, $_data["action"]),
'msg' => array('object_modified', $username)
);
- break;
- case "get_user_cids":
+ break;
+ case "get_user_cids":
// Used to exclude existing CredentialIds while registering
$username = $_SESSION['mailcow_cc_username'];
- if ($_SESSION['mailcow_cc_role'] != "domainadmin" &&
- $_SESSION['mailcow_cc_role'] != "admin") {
- return false;
+ if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
+ return false;
}
$stmt = $pdo->prepare("SELECT `credentialId` FROM `fido2` WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
@@ -1055,8 +1300,8 @@
$cids[] = $row['credentialId'];
}
return $cids;
- break;
- case "get_all_cids":
+ break;
+ case "get_all_cids":
// Only needed when using fido2 with username
$stmt = $pdo->query("SELECT `credentialId` FROM `fido2`");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
@@ -1064,7 +1309,7 @@
$cids[] = $row['credentialId'];
}
return $cids;
- break;
+ break;
case "get_by_b64cid":
if (!isset($_data['cid']) || empty($_data['cid'])) {
return false;
@@ -1080,12 +1325,11 @@
$data['subject'] = $row['certificateSubject'];
$data['cid'] = $row['cid'];
return $data;
- break;
- case "get_friendly_names":
+ break;
+ case "get_friendly_names":
$username = $_SESSION['mailcow_cc_username'];
- if ($_SESSION['mailcow_cc_role'] != "domainadmin" &&
- $_SESSION['mailcow_cc_role'] != "admin") {
- return false;
+ if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
+ return false;
}
$stmt = $pdo->prepare("SELECT SHA2(`credentialId`, 256) AS `cid`, `created`, `certificateSubject`, `friendlyName` FROM `fido2` WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
@@ -1098,39 +1342,37 @@
);
}
return $fns;
- break;
- case "unset_fido2_key":
+ break;
+ case "unset_fido2_key":
$username = $_SESSION['mailcow_cc_username'];
- if ($_SESSION['mailcow_cc_role'] != "domainadmin" &&
- $_SESSION['mailcow_cc_role'] != "admin") {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_data["action"]),
- 'msg' => 'access_denied'
- );
- return false;
+ if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_data["action"]),
+ 'msg' => 'access_denied'
+ );
+ return false;
}
$stmt = $pdo->prepare("DELETE FROM `fido2` WHERE `username` = :username AND SHA2(`credentialId`, 256) = :cid");
$stmt->execute(array(
':username' => $username,
':cid' => $_data['post_data']['unset_fido2_key']
));
- $_SESSION['return'][] = array(
- 'type' => 'success',
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
'log' => array(__FUNCTION__, $_data_log),
- 'msg' => array('object_modified', htmlspecialchars($username))
- );
- break;
+ 'msg' => array('object_modified', htmlspecialchars($username))
+ );
+ break;
case "edit_fn":
$username = $_SESSION['mailcow_cc_username'];
- if ($_SESSION['mailcow_cc_role'] != "domainadmin" &&
- $_SESSION['mailcow_cc_role'] != "admin") {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_data["action"]),
- 'msg' => 'access_denied'
- );
- return false;
+ if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_data["action"]),
+ 'msg' => 'access_denied'
+ );
+ return false;
}
$stmt = $pdo->prepare("UPDATE `fido2` SET `friendlyName` = :friendlyName WHERE SHA2(`credentialId`, 256) = :cid AND `username` = :username");
$stmt->execute(array(
@@ -1138,13 +1380,13 @@
':friendlyName' => $_data['fido2_attrs']['fido2_fn'],
':cid' => $_data['fido2_attrs']['fido2_cid']
));
- $_SESSION['return'][] = array(
- 'type' => 'success',
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
'log' => array(__FUNCTION__, $_data_log),
- 'msg' => array('object_modified', htmlspecialchars($username))
- );
- break;
- }
+ 'msg' => array('object_modified', htmlspecialchars($username))
+ );
+ break;
+ }
}
function unset_tfa_key($_data) {
// Can only unset own keys
@@ -1154,14 +1396,13 @@
$_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(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_data_log),
- 'msg' => 'access_denied'
- );
- return false;
+ if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_data_log),
+ 'msg' => 'access_denied'
+ );
+ return false;
}
try {
if (!is_numeric($id)) {
@@ -1202,7 +1443,7 @@
}
}
function get_tfa($username = null) {
- global $pdo;
+ global $pdo;
if (isset($_SESSION['mailcow_cc_username'])) {
$username = $_SESSION['mailcow_cc_username'];
}
@@ -1214,76 +1455,83 @@
$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;
+ if (isset($row["authmech"])) {
+ 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;
- default:
- $data['name'] = 'none';
- $data['pretty'] = "-";
- 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;
+ }
+ }
+ else {
+ $data['name'] = 'none';
+ $data['pretty'] = "-";
+ return $data;
+ }
}
function verify_tfa_login($username, $token) {
- global $pdo;
- global $yubi;
- global $u2f;
- global $tfa;
+ global $pdo;
+ 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(
- 'type' => 'danger',
+ switch ($row["authmech"]) {
+ case "yubi_otp":
+ if (!ctype_alnum($token) || strlen($token) != 44) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__, $username, '*'),
- 'msg' => array('yotp_verification_failed', 'token length error')
- );
+ 'msg' => array('yotp_verification_failed', 'token length error')
+ );
return false;
}
$yubico_modhex_id = substr($token, 0, 12);
@@ -1298,20 +1546,20 @@
$yubi = new Auth_Yubico($yubico_auth[0], $yubico_auth[1]);
$yauth = $yubi->verify($token);
if (PEAR::isError($yauth)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__, $username, '*'),
- 'msg' => array('yotp_verification_failed', $yauth->getMessage())
- );
- return false;
+ 'msg' => array('yotp_verification_failed', $yauth->getMessage())
+ );
+ return false;
}
else {
$_SESSION['tfa_id'] = $row['id'];
- $_SESSION['return'][] = array(
- 'type' => 'success',
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
'log' => array(__FUNCTION__, $username, '*'),
- 'msg' => 'verified_yotp_login'
- );
+ 'msg' => 'verified_yotp_login'
+ );
return true;
}
$_SESSION['return'][] = array(
@@ -1396,31 +1644,34 @@
);
return false;
break;
- }
+ }
return false;
}
function admin_api($access, $action, $data = null) {
- global $pdo;
- if ($_SESSION['mailcow_cc_role'] != "admin") {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ global $pdo;
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__),
- 'msg' => 'access_denied'
- );
- return false;
- }
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
if ($access !== "ro" && $access !== "rw") {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__),
- 'msg' => 'invalid access type'
- );
- return false;
+ 'msg' => 'invalid access type'
+ );
+ return false;
}
if ($action == "edit") {
$active = (!empty($data['active'])) ? 1 : 0;
$skip_ip_check = (isset($data['skip_ip_check'])) ? 1 : 0;
- $allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $data['allow_from']));
+ $allow_from = array();
+ if (isset($data['allow_from'])) {
+ $allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $data['allow_from']));
+ }
foreach ($allow_from as $key => $val) {
if (empty($val)) {
unset($allow_from[$key]);
@@ -1507,29 +1758,31 @@
elseif ($action == "get") {
$stmt = $pdo->query("SELECT * FROM `api` WHERE `access` = '" . $access . "'");
$apidata = $stmt->fetch(PDO::FETCH_ASSOC);
- $apidata['allow_from'] = str_replace(',', PHP_EOL, $apidata['allow_from']);
+ if ($apidata !== false) {
+ $apidata['allow_from'] = str_replace(',', PHP_EOL, $apidata['allow_from']);
+ }
return $apidata;
}
- $_SESSION['return'][] = array(
- 'type' => 'success',
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
'log' => array(__FUNCTION__, $data),
- 'msg' => 'admin_api_modified'
- );
+ 'msg' => 'admin_api_modified'
+ );
}
function license($action, $data = null) {
- global $pdo;
- global $redis;
- global $lang;
- if ($_SESSION['mailcow_cc_role'] != "admin") {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ global $pdo;
+ global $redis;
+ global $lang;
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__),
- 'msg' => 'access_denied'
- );
- return false;
- }
- switch ($action) {
- case "verify":
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ switch ($action) {
+ case "verify":
// Keep result until revalidate button is pressed or session expired
$stmt = $pdo->query("SELECT `version` FROM `versions` WHERE `application` = 'GUID'");
$versions = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -1588,16 +1841,16 @@
}
}
function rspamd_ui($action, $data = null) {
- if ($_SESSION['mailcow_cc_role'] != "admin") {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__),
- 'msg' => 'access_denied'
- );
- return false;
- }
- switch ($action) {
- case "edit":
+ '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)) {
@@ -1673,11 +1926,11 @@
$to = intval($to);
if ($from < 1 || $to < $from) { return false; }
}
- global $redis;
- global $pdo;
- if ($_SESSION['mailcow_cc_role'] != "admin") {
- return false;
- }
+ global $redis;
+ global $pdo;
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ return false;
+ }
// SQL
if ($application == "mailcow-ui") {
if (isset($from) && isset($to)) {
@@ -1699,6 +1952,26 @@
return $data;
}
}
+ if ($application == "sasl") {
+ if (isset($from) && isset($to)) {
+ $stmt = $pdo->prepare("SELECT * FROM `sasl_log` ORDER BY `datetime` DESC LIMIT :from, :to");
+ $stmt->execute(array(
+ ':from' => $from - 1,
+ ':to' => $to
+ ));
+ $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ }
+ else {
+ $stmt = $pdo->prepare("SELECT * FROM `sasl_log` ORDER BY `datetime` DESC LIMIT :lines");
+ $stmt->execute(array(
+ ':lines' => $lines + 1,
+ ));
+ $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ }
+ if (is_array($data)) {
+ return $data;
+ }
+ }
// Redis
if ($application == "dovecot-mailcow") {
if (isset($from) && isset($to)) {
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.mailbox.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.mailbox.inc.php
index fff4190..24e5dab 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.mailbox.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.mailbox.inc.php
@@ -35,7 +35,7 @@
else {
$username = $_SESSION['mailcow_cc_username'];
}
- if (!is_numeric($_data["validity"]) || $_data["validity"] > 672) {
+ if (isset($_data["validity"]) && !filter_var($_data["validity"], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 87600)))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
@@ -43,8 +43,17 @@
);
return false;
}
- $domain = mailbox('get', 'mailbox_details', $username)['domain'];
- if (!is_valid_domain_name($domain)) {
+ else {
+ // Default to 1 yr
+ $_data["validity"] = 8760;
+ }
+ $domain = $_data['domain'];
+ $valid_domains[] = mailbox('get', 'mailbox_details', $username)['domain'];
+ $valid_alias_domains = user_get_alias_details($username)['alias_domains'];
+ if (!empty($valid_alias_domains)) {
+ $valid_domains = array_merge($valid_domains, $valid_alias_domains);
+ }
+ if (!in_array($domain, $valid_domains)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
@@ -52,13 +61,11 @@
);
return false;
}
- $validity = strtotime("+".$_data["validity"]." hour");
- $letters = 'abcefghijklmnopqrstuvwxyz1234567890';
- $random_name = substr(str_shuffle($letters), 0, 24);
+ $validity = strtotime("+" . $_data["validity"] . " hour");
$stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `goto`, `validity`) VALUES
(:address, :goto, :validity)");
$stmt->execute(array(
- ':address' => $random_name . '@' . $domain,
+ ':address' => readable_random_string(rand(rand(3, 9), rand(3, 9))) . '.' . readable_random_string(rand(rand(3, 9), rand(3, 9))) . '@' . $domain,
':goto' => $username,
':validity' => $validity
));
@@ -441,17 +448,17 @@
);
return false;
}
- $domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
+ $domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
$description = $_data['description'];
if (empty($description)) {
$description = $domain;
}
- $aliases = $_data['aliases'];
- $mailboxes = $_data['mailboxes'];
- $defquota = $_data['defquota'];
- $maxquota = $_data['maxquota'];
- $restart_sogo = $_data['restart_sogo'];
- $quota = $_data['quota'];
+ $aliases = (int)$_data['aliases'];
+ $mailboxes = (int)$_data['mailboxes'];
+ $defquota = (int)$_data['defquota'];
+ $maxquota = (int)$_data['maxquota'];
+ $restart_sogo = (int)$_data['restart_sogo'];
+ $quota = (int)$_data['quota'];
if ($defquota > $maxquota) {
$_SESSION['return'][] = array(
'type' => 'danger',
@@ -673,9 +680,10 @@
continue;
}
}
+ $gotos = array_unique($gotos);
$gotos = array_filter($gotos);
if (empty($gotos)) { return false; }
- $goto = implode(",", $gotos);
+ $goto = implode(",", (array)$gotos);
}
foreach ($addresses as $address) {
if (empty($address)) {
@@ -928,7 +936,7 @@
$password = $_data['password'];
$password2 = $_data['password2'];
$name = ltrim(rtrim($_data['name'], '>'), '<');
- $quota_m = intval($_data['quota']);
+ $quota_m = intval($_data['quota']);
if ((!isset($_SESSION['acl']['unlimited_quota']) || $_SESSION['acl']['unlimited_quota'] != "1") && $quota_m === 0) {
$_SESSION['return'][] = array(
'type' => 'danger',
@@ -948,9 +956,10 @@
$imap_access = (isset($_data['imap_access'])) ? intval($_data['imap_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['imap_access']);
$pop3_access = (isset($_data['pop3_access'])) ? intval($_data['pop3_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['pop3_access']);
$smtp_access = (isset($_data['smtp_access'])) ? intval($_data['smtp_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['smtp_access']);
+ $relayhost = (isset($_data['relayhost'])) ? intval($_data['relayhost']) : 0;
$quarantine_notification = (isset($_data['quarantine_notification'])) ? strval($_data['quarantine_notification']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']);
$quarantine_category = (isset($_data['quarantine_category'])) ? strval($_data['quarantine_category']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
- $quota_b = ($quota_m * 1048576);
+ $quota_b = ($quota_m * 1048576);
$mailbox_attrs = json_encode(
array(
'force_pw_update' => strval($force_pw_update),
@@ -960,6 +969,8 @@
'imap_access' => strval($imap_access),
'pop3_access' => strval($pop3_access),
'smtp_access' => strval($smtp_access),
+ 'relayhost' => strval($relayhost),
+ 'passwd_update' => time(),
'mailbox_format' => strval($MAILBOX_DEFAULT_ATTRIBUTES['mailbox_format']),
'quarantine_notification' => strval($quarantine_notification),
'quarantine_category' => strval($quarantine_category)
@@ -989,7 +1000,7 @@
COUNT(*) as count,
COALESCE(ROUND(SUM(`quota`)/1048576), 0) as `quota`
FROM `mailbox`
- WHERE `kind` NOT REGEXP 'location|thing|group'
+ WHERE (`kind` = '' OR `kind` = NULL)
AND `domain` = :domain");
$stmt->execute(array(':domain' => $domain));
$MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -1037,39 +1048,10 @@
);
return false;
}
- if (!empty($password) && !empty($password2)) {
- if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
- 'msg' => 'password_complexity'
- );
- return false;
- }
- if ($password != $password2) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
- 'msg' => 'password_mismatch'
- );
- return false;
- }
- // support pre hashed passwords
- if (preg_match('/^({SSHA256}|{SSHA}|{SHA512-CRYPT}|{SSHA512}|{MD5-CRYPT}|{PLAIN-MD5})/i', $password)) {
- $password_hashed = $password;
- }
- else {
- $password_hashed = hash_password($password);
- }
- }
- else {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
- 'msg' => 'password_empty'
- );
+ if (password_check($password, $password2) !== true) {
return false;
}
+ $password_hashed = hash_password($password);
if ($MailboxData['count'] >= $DomainData['mailboxes']) {
$_SESSION['return'][] = array(
'type' => 'danger',
@@ -1107,6 +1089,12 @@
':mailbox_attrs' => $mailbox_attrs,
':active' => $active
));
+ $stmt = $pdo->prepare("UPDATE `mailbox` SET
+ `attributes` = JSON_SET(`attributes`, '$.passwd_update', NOW())
+ WHERE `username` = :username");
+ $stmt->execute(array(
+ ':username' => $username
+ ));
$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));
@@ -1506,8 +1494,8 @@
);
continue;
}
- $lowspamlevel = explode(',', $_data['spam_score'])[0];
- $highspamlevel = explode(',', $_data['spam_score'])[1];
+ $lowspamlevel = explode(',', $_data['spam_score'])[0];
+ $highspamlevel = explode(',', $_data['spam_score'])[1];
if (!is_numeric($lowspamlevel) || !is_numeric($highspamlevel)) {
$_SESSION['return'][] = array(
'type' => 'danger',
@@ -1516,6 +1504,9 @@
);
continue;
}
+ if ($lowspamlevel == $highspamlevel) {
+ $highspamlevel = $highspamlevel + 0.1;
+ }
$stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username
AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')");
$stmt->execute(array(
@@ -1581,7 +1572,7 @@
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
- 'msg' => array('mailbox_modified', htmlspecialchars(implode(', ', $usernames)))
+ 'msg' => array('mailbox_modified', htmlspecialchars(implode(', ', (array)$usernames)))
);
}
break;
@@ -1932,6 +1923,52 @@
);
continue;
}
+ if ($_data['expand_alias'] === true || $_data['expand_alias'] == 1) {
+ $stmt = $pdo->prepare("SELECT `address` FROM `alias`
+ WHERE `address` = :address
+ AND `domain` NOT IN (
+ SELECT `alias_domain` FROM `alias_domain`
+ )");
+ $stmt->execute(array(
+ ':address' => $address,
+ ));
+ $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
+ if ($num_results == 0) {
+ $_SESSION['return'][] = array(
+ 'type' => 'warning',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('is_not_primary_alias', htmlspecialchars($address))
+ );
+ continue;
+ }
+ $stmt = $pdo->prepare("SELECT `goto`, GROUP_CONCAT(CONCAT(SUBSTRING(`alias`.`address`, 1, LOCATE('@', `alias`.`address`) - 1), '@', `alias_domain`.`alias_domain`)) AS `missing_alias`
+ FROM `alias` JOIN `alias_domain` ON `alias_domain`.`target_domain` = `alias`.`domain`
+ WHERE CONCAT(SUBSTRING(`alias`.`address`, 1, LOCATE('@', `alias`.`address`) - 1), '@', `alias_domain`.`alias_domain`) NOT IN (
+ SELECT `address` FROM `alias` WHERE `address` != `goto`
+ )
+ AND `alias`.`address` NOT IN (
+ SELECT `address` FROM `alias` WHERE `address` = `goto`
+ )
+ AND `address` = :address ;");
+ $stmt->execute(array(
+ ':address' => $address
+ ));
+ $missing_aliases = $stmt->fetch(PDO::FETCH_ASSOC);
+ if (!empty($missing_aliases['missing_alias'])) {
+ mailbox('add', 'alias', array(
+ 'address' => $missing_aliases['missing_alias'],
+ 'goto' => $missing_aliases['goto'],
+ 'sogo_visible' => 1,
+ 'active' => 1
+ ));
+ }
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('alias_modified', htmlspecialchars($address))
+ );
+ continue;
+ }
$domain = idn_to_ascii(substr(strstr($address, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
if ($is_now['address'] != $address) {
$local_part = strstr($address, '@', true);
@@ -2041,8 +2078,9 @@
':address' => $address
));
}
+ $gotos = array_unique($gotos);
$gotos = array_filter($gotos);
- $goto = implode(",", $gotos);
+ $goto = implode(",", (array)$gotos);
}
if (!empty($goto)) {
$stmt = $pdo->prepare("UPDATE `alias` SET
@@ -2096,6 +2134,7 @@
if (!empty($is_now)) {
$gal = (isset($_data['gal'])) ? intval($_data['gal']) : $is_now['gal'];
$description = (!empty($_data['description']) && isset($_SESSION['acl']['domain_desc']) && $_SESSION['acl']['domain_desc'] == "1") ? $_data['description'] : $is_now['description'];
+ (int)$relayhost = (isset($_data['relayhost']) && isset($_SESSION['acl']['domain_relayhost']) && $_SESSION['acl']['domain_relayhost'] == "1") ? intval($_data['relayhost']) : intval($is_now['relayhost']);
}
else {
$_SESSION['return'][] = array(
@@ -2157,7 +2196,7 @@
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'
+ WHERE (`kind` = '' OR `kind` = NULL)
AND domain = :domain");
$stmt->execute(array(':domain' => $domain));
$MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -2300,6 +2339,7 @@
(int)$imap_access = (isset($_data['imap_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['imap_access']) : intval($is_now['attributes']['imap_access']);
(int)$pop3_access = (isset($_data['pop3_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['pop3_access']) : intval($is_now['attributes']['pop3_access']);
(int)$smtp_access = (isset($_data['smtp_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['smtp_access']) : intval($is_now['attributes']['smtp_access']);
+ (int)$relayhost = (isset($_data['relayhost']) && isset($_SESSION['acl']['mailbox_relayhost']) && $_SESSION['acl']['mailbox_relayhost'] == "1") ? intval($_data['relayhost']) : intval($is_now['attributes']['relayhost']);
(int)$quota_m = (isset_has_content($_data['quota'])) ? intval($_data['quota']) : ($is_now['quota'] / 1048576);
$name = (!empty($_data['name'])) ? ltrim(rtrim($_data['name'], '>'), '<') : $is_now['name'];
$domain = $is_now['domain'];
@@ -2324,11 +2364,6 @@
);
return false;
}
- $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(
'type' => 'danger',
@@ -2337,15 +2372,8 @@
);
continue;
}
- if ($quota_m > $DomainData['maxquota']) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
- 'msg' => array('mailbox_quota_exceeded', $DomainData['maxquota'])
- );
- continue;
- }
- if (((($is_now['quota_used'] / 1048576) - $quota_m) + $quota_m) > $DomainData['quota']) {
+ $DomainData = mailbox('get', 'domain_details', $domain);
+ if ($quota_m > ($is_now['max_new_quota'] / 1048576)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
@@ -2353,6 +2381,14 @@
);
continue;
}
+ if ($quota_m > $DomainData['max_quota_for_mbox']) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('mailbox_quota_exceeded', $DomainData['max_quota_for_mbox'])
+ );
+ continue;
+ }
$extra_acls = array();
if (isset($_data['extended_sender_acl'])) {
if (!isset($_SESSION['acl']['extend_sender_acl']) || $_SESSION['acl']['extend_sender_acl'] != "1" ) {
@@ -2539,39 +2575,21 @@
));
}
}
- if (!empty($password) && !empty($password2)) {
- if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
- 'msg' => 'password_complexity'
- );
+ if (!empty($password)) {
+ if (password_check($password, $password2) !== true) {
continue;
}
- if ($password != $password2) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
- 'msg' => 'password_mismatch'
- );
- continue;
- }
- // support pre hashed passwords
- if (preg_match('/^({SSHA256}|{SSHA}|{SHA512-CRYPT}|{SSHA512}|{MD5-CRYPT}|{PLAIN-MD5})/i', $password)) {
- $password_hashed = $password;
- }
- else {
- $password_hashed = hash_password($password);
- }
+ $password_hashed = hash_password($password);
$stmt = $pdo->prepare("UPDATE `mailbox` SET
- `password` = :password_hashed
+ `password` = :password_hashed,
+ `attributes` = JSON_SET(`attributes`, '$.passwd_update', NOW())
WHERE `username` = :username");
$stmt->execute(array(
':password_hashed' => $password_hashed,
':username' => $username
));
}
- // We could either set alias = 1 if alias = 2 or tune the Postfix alias table (that's what we did, TODO: to it the other way)
+ // We could either set alias = 1 if alias = 2 or tune the Postfix alias table (that's what we did, TODO: do it the other way)
$stmt = $pdo->prepare("UPDATE `alias` SET
`active` = :active
WHERE `address` = :address");
@@ -2587,6 +2605,7 @@
`attributes` = JSON_SET(`attributes`, '$.sogo_access', :sogo_access),
`attributes` = JSON_SET(`attributes`, '$.imap_access', :imap_access),
`attributes` = JSON_SET(`attributes`, '$.pop3_access', :pop3_access),
+ `attributes` = JSON_SET(`attributes`, '$.relayhost', :relayhost),
`attributes` = JSON_SET(`attributes`, '$.smtp_access', :smtp_access)
WHERE `username` = :username");
$stmt->execute(array(
@@ -2598,6 +2617,7 @@
':imap_access' => $imap_access,
':pop3_access' => $pop3_access,
':smtp_access' => $smtp_access,
+ ':relayhost' => $relayhost,
':username' => $username
));
$_SESSION['return'][] = array(
@@ -2819,7 +2839,7 @@
return false;
}
elseif (isset($_data) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
- $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND `domain` = :domain");
+ $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE (`kind` = '' OR `kind` = NULL) AND `domain` = :domain");
$stmt->execute(array(
':domain' => $_data,
));
@@ -2829,7 +2849,7 @@
}
}
else {
- $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 = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE (`kind` = '' OR `kind` = NULL) 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'],
@@ -2982,7 +3002,7 @@
while($field = array_shift($fields)) {
$shown_fields[] = $field['Field'];
}
- $stmt = $pdo->prepare("SELECT " . implode(',', $shown_fields) . ",
+ $stmt = $pdo->prepare("SELECT " . implode(',', (array)$shown_fields) . ",
`active`
FROM `imapsync` WHERE id = :id");
}
@@ -2997,7 +3017,7 @@
while($field = array_shift($fields)) {
$shown_fields[] = $field['Field'];
}
- $stmt = $pdo->prepare("SELECT " . implode(',', $shown_fields) . ",
+ $stmt = $pdo->prepare("SELECT " . implode(',', (array)$shown_fields) . ",
`active`
FROM `imapsync` WHERE id = :id");
}
@@ -3113,7 +3133,9 @@
}
$stmt = $pdo->prepare("SELECT `address`,
`goto`,
- `validity`
+ `validity`,
+ `created`,
+ `modified`
FROM `spamalias`
WHERE `goto` = :username
AND `validity` >= :unixnow");
@@ -3362,10 +3384,10 @@
if (empty($row)) {
return false;
}
- $stmt = $pdo->prepare("SELECT COUNT(*) AS `count`,
+ $stmt = $pdo->prepare("SELECT COUNT(`username`) AS `count`,
COALESCE(SUM(`quota`), 0) AS `in_use`
FROM `mailbox`
- WHERE `kind` NOT REGEXP 'location|thing|group'
+ WHERE (`kind` = '' OR `kind` = NULL)
AND `domain` = :domain");
$stmt->execute(array(':domain' => $row['domain']));
$MailboxDataDomain = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -3377,7 +3399,7 @@
$stmt->execute(array(':domain' => $row['domain']));
$SumQuotaInUse = $stmt->fetch(PDO::FETCH_ASSOC);
$rl = ratelimit('get', 'domain', $_data);
- $domaindata['max_new_mailbox_quota'] = ($row['quota'] * 1048576) - $MailboxDataDomain['in_use'];
+ $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);
}
@@ -3399,7 +3421,7 @@
$domaindata['msgs_total'] = 0;
}
$domaindata['mboxes_in_domain'] = $MailboxDataDomain['count'];
- $domaindata['mboxes_left'] = $row['mailboxes'] - $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'];
@@ -3419,7 +3441,7 @@
$domaindata['relay_all_recipients_int'] = $row['relay_all_recipients'];
$domaindata['relay_unknown_only'] = $row['relay_unknown_only'];
$domaindata['relay_unknown_only_int'] = $row['relay_unknown_only'];
- $stmt = $pdo->prepare("SELECT COUNT(*) AS `alias_count` FROM `alias`
+ $stmt = $pdo->prepare("SELECT COUNT(`address`) 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`
@@ -3430,7 +3452,7 @@
));
$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'];
+ $domaindata['aliases_left'] = $row['aliases'] - $AliasDataDomain['alias_count'];
if ($_SESSION['mailcow_cc_role'] == "admin")
{
$stmt = $pdo->prepare("SELECT GROUP_CONCAT(`username` SEPARATOR ', ') AS domain_admins FROM `domain_admins` WHERE `domain` = :domain");
@@ -3447,19 +3469,6 @@
return false;
}
$mailboxdata = array();
- $rl = ratelimit('get', 'mailbox', $_data);
- $last_imap_login = $redis->Get('last-login/imap/' . $_data);
- $last_smtp_login = $redis->Get('last-login/smtp/' . $_data);
- $last_pop3_login = $redis->Get('last-login/pop3/' . $_data);
- if ($last_imap_login === false || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
- $last_imap_login = '0';
- }
- if ($last_smtp_login === false || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
- $last_smtp_login = '0';
- }
- if ($last_pop3_login === false || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
- $last_pop3_login = '0';
- }
if (preg_match('/y|yes/i', getenv('MASTER'))) {
$stmt = $pdo->prepare("SELECT
`domain`.`backupmx`,
@@ -3473,7 +3482,10 @@
`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");
+ WHERE (`mailbox`.`kind` = '' OR `mailbox`.`kind` = NULL)
+ AND `mailbox`.`username` = `quota2`.`username`
+ AND `domain`.`domain` = `mailbox`.`domain`
+ AND `mailbox`.`username` = :mailbox");
}
else {
$stmt = $pdo->prepare("SELECT
@@ -3488,53 +3500,29 @@
`attributes`,
`quota2replica`.`messages`
FROM `mailbox`, `quota2replica`, `domain`
- WHERE `mailbox`.`kind` NOT REGEXP 'location|thing|group' AND `mailbox`.`username` = `quota2replica`.`username` AND `domain`.`domain` = `mailbox`.`domain` AND `mailbox`.`username` = :mailbox");
+ WHERE (`mailbox`.`kind` = '' OR `mailbox`.`kind` = NULL)
+ AND `mailbox`.`username` = `quota2replica`.`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 IFNULL(COUNT(`active`), 0) AS `pushover_active` FROM `pushover` WHERE `username` = :username AND `active` = 1");
- $stmt->execute(array(':username' => $_data));
- $PushoverActive = $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'];
- if (!empty($rl)) {
- $mailboxdata['rl'] = $rl;
- $mailboxdata['rl_scope'] = 'mailbox';
- }
- else {
- $mailboxdata['rl'] = ratelimit('get', 'domain', $row['domain']);
- $mailboxdata['rl_scope'] = 'domain';
- }
- $mailboxdata['is_relayed'] = $row['backupmx'];
- $mailboxdata['name'] = $row['name'];
- $mailboxdata['last_imap_login'] = $last_imap_login;
- $mailboxdata['last_smtp_login'] = $last_smtp_login;
- $mailboxdata['last_pop3_login'] = $last_pop3_login;
$mailboxdata['active'] = $row['active'];
$mailboxdata['active_int'] = $row['active'];
$mailboxdata['domain'] = $row['domain'];
+ $mailboxdata['relayhost'] = $row['relayhost'];
+ $mailboxdata['name'] = $row['name'];
$mailboxdata['local_part'] = $row['local_part'];
$mailboxdata['quota'] = $row['quota'];
+ $mailboxdata['messages'] = $row['messages'];
$mailboxdata['attributes'] = json_decode($row['attributes'], true);
$mailboxdata['quota_used'] = intval($row['bytes']);
$mailboxdata['percent_in_use'] = ($row['quota'] == 0) ? '- ' : round((intval($row['bytes']) / intval($row['quota'])) * 100);
- $mailboxdata['messages'] = $row['messages'];
- $mailboxdata['spam_aliases'] = $SpamaliasUsage['sa_count'];
- $mailboxdata['pushover_active'] = ($PushoverActive['pushover_active'] == 1) ? 1 : 0;
+
if ($mailboxdata['percent_in_use'] === '- ') {
$mailboxdata['percent_class'] = "info";
}
@@ -3547,6 +3535,69 @@
else {
$mailboxdata['percent_class'] = "success";
}
+
+ // Determine last logins
+ $stmt = $pdo->prepare("SELECT MAX(`datetime`) AS `datetime`, `service` FROM `sasl_log`
+ WHERE `username` = :mailbox
+ GROUP BY `service` DESC");
+ $stmt->execute(array(':mailbox' => $_data));
+ $SaslLogsData = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ foreach ($SaslLogsData as $SaslLogs) {
+ if ($SaslLogs['service'] == 'imap') {
+ $last_imap_login = strtotime($SaslLogs['datetime']);
+ }
+ else if ($SaslLogs['service'] == 'smtp') {
+ $last_smtp_login = strtotime($SaslLogs['datetime']);
+ }
+ else if ($SaslLogs['service'] == 'pop3') {
+ $last_pop3_login = strtotime($SaslLogs['datetime']);
+ }
+ }
+ if (!isset($last_imap_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
+ $last_imap_login = 0;
+ }
+ if (!isset($last_smtp_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
+ $last_smtp_login = 0;
+ }
+ if (!isset($last_pop3_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
+ $last_pop3_login = 0;
+ }
+ $mailboxdata['last_imap_login'] = $last_imap_login;
+ $mailboxdata['last_smtp_login'] = $last_smtp_login;
+ $mailboxdata['last_pop3_login'] = $last_pop3_login;
+
+ if (!isset($_extra) || $_extra != 'reduced') {
+ $rl = ratelimit('get', 'mailbox', $_data);
+ $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 IFNULL(COUNT(`active`), 0) AS `pushover_active` FROM `pushover` WHERE `username` = :username AND `active` = 1");
+ $stmt->execute(array(':username' => $_data));
+ $PushoverActive = $stmt->fetch(PDO::FETCH_ASSOC);
+ $stmt = $pdo->prepare("SELECT COALESCE(SUM(`quota`), 0) as `in_use` FROM `mailbox` WHERE (`kind` = '' OR `kind` = NULL) 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'];
+ $mailboxdata['spam_aliases'] = $SpamaliasUsage['sa_count'];
+ $mailboxdata['pushover_active'] = ($PushoverActive['pushover_active'] == 1) ? 1 : 0;
+ if ($mailboxdata['max_new_quota'] > ($DomainQuota['maxquota'] * 1048576)) {
+ $mailboxdata['max_new_quota'] = ($DomainQuota['maxquota'] * 1048576);
+ }
+ if (!empty($rl)) {
+ $mailboxdata['rl'] = $rl;
+ $mailboxdata['rl_scope'] = 'mailbox';
+ }
+ else {
+ $mailboxdata['rl'] = ratelimit('get', 'domain', $row['domain']);
+ $mailboxdata['rl_scope'] = 'domain';
+ }
+ $mailboxdata['is_relayed'] = $row['backupmx'];
+ }
+
return $mailboxdata;
break;
case 'resource_details':
@@ -3826,7 +3877,7 @@
);
continue;
}
- $domain = idn_to_ascii(strtolower(trim($domain)), 0, INTL_IDNA_VARIANT_UTS46);
+ $domain = idn_to_ascii(strtolower(trim($domain)), 0, INTL_IDNA_VARIANT_UTS46);
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
WHERE `domain` = :domain");
$stmt->execute(array(':domain' => $domain));
@@ -4163,6 +4214,14 @@
$stmt->execute(array(
':username' => $username
));
+ $stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
+ $stmt->execute(array(
+ ':username' => $username,
+ ));
+ $stmt = $pdo->prepare("DELETE FROM `fido2` WHERE `username` = :username");
+ $stmt->execute(array(
+ ':username' => $username,
+ ));
$stmt = $pdo->prepare("SELECT `address`, `goto` FROM `alias`
WHERE `goto` REGEXP :username");
$stmt->execute(array(':username' => '(^|,)'.$username.'($|,)'));
@@ -4172,7 +4231,7 @@
if (($key = array_search($username, $goto_exploded)) !== false) {
unset($goto_exploded[$key]);
}
- $gotos_rebuild = implode(',', $goto_exploded);
+ $gotos_rebuild = implode(',', (array)$goto_exploded);
$stmt = $pdo->prepare("UPDATE `alias` SET
`goto` = :goto
WHERE `address` = :address");
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.oauth2.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.oauth2.inc.php
index 7bc7dea..7dc5602 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.oauth2.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.oauth2.inc.php
@@ -1,16 +1,16 @@
<?php
function oauth2($_action, $_type, $_data = null) {
- global $pdo;
- global $redis;
- global $lang;
- if ($_SESSION['mailcow_cc_role'] != "admin") {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
+ global $pdo;
+ global $redis;
+ global $lang;
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data),
- 'msg' => 'access_denied'
- );
- return false;
- }
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
switch ($_action) {
case 'add':
switch ($_type) {
@@ -188,7 +188,7 @@
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_type, $_data),
- 'msg' => sprintf($lang['success']['items_deleted'], implode(', ', $access_tokens))
+ 'msg' => sprintf($lang['success']['items_deleted'], implode(', ', (array)$access_tokens))
);
break;
case 'refresh_token':
@@ -210,7 +210,7 @@
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_type, $_data),
- 'msg' => sprintf($lang['success']['items_deleted'], implode(', ', $refresh_tokens))
+ 'msg' => sprintf($lang['success']['items_deleted'], implode(', ', (array)$refresh_tokens))
);
break;
}
@@ -239,4 +239,4 @@
}
break;
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.policy.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.policy.inc.php
index ad29bd2..498f991 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.policy.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.policy.inc.php
@@ -1,9 +1,9 @@
<?php
function policy($_action, $_scope, $_data = null) {
- global $pdo;
- global $redis;
- global $lang;
- $_data_log = $_data;
+ global $pdo;
+ global $redis;
+ global $lang;
+ $_data_log = $_data;
switch ($_action) {
case 'add':
if (!isset($_SESSION['acl']['spam_policy']) || $_SESSION['acl']['spam_policy'] != "1" ) {
@@ -261,7 +261,7 @@
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
- 'msg' => array('items_deleted', implode(', ', $prefids))
+ 'msg' => array('items_deleted', implode(', ', (array)$prefids))
);
}
break;
@@ -317,4 +317,4 @@
}
break;
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.pushover.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.pushover.inc.php
index e8d4670..74e8bb1 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.pushover.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.pushover.inc.php
@@ -1,6 +1,6 @@
<?php
function pushover($_action, $_data = null) {
- global $pdo;
+ global $pdo;
switch ($_action) {
case 'edit':
if (!isset($_SESSION['acl']['pushover']) || $_SESSION['acl']['pushover'] != "1" ) {
@@ -81,7 +81,7 @@
}
$senders = array_filter($senders);
if (empty($senders)) { $senders = ''; }
- $senders = implode(",", $senders);
+ $senders = implode(",", (array)$senders);
if (!ctype_alnum($key) || strlen($key) != 30) {
$_SESSION['return'][] = array(
'type' => 'danger',
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.quota_notification.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.quota_notification.inc.php
index 9ca5a22..9f58bfb 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.quota_notification.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.quota_notification.inc.php
@@ -65,3 +65,86 @@
break;
}
}
+function quota_notification_bcc($_action, $_data = null) {
+ global $redis;
+ $_data_log = $_data;
+ if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ switch ($_action) {
+ case 'edit':
+ $domain = $_data['domain'];
+ if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ $active = intval($_data['active']);
+ $bcc_rcpts = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['bcc_rcpt']));
+ foreach ($bcc_rcpts as $i => &$rcpt) {
+ $rcpt = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $rcpt);
+ if (!empty($rcpt) && filter_var($rcpt, FILTER_VALIDATE_EMAIL) === false) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => array('goto_invalid', htmlspecialchars($rcpt))
+ );
+ unset($bcc_rcpts[$i]);
+ continue;
+ }
+ }
+ $bcc_rcpts = array_unique($bcc_rcpts);
+ $bcc_rcpts = array_filter($bcc_rcpts);
+ if (empty($bcc_rcpts)) {
+ $active = 0;
+
+ }
+ try {
+ $redis->hSet('QW_BCC', $domain, json_encode(array('bcc_rcpts' => $bcc_rcpts, 'active' => $active)));
+ }
+ catch (RedisException $e) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => array('redis_error', $e)
+ );
+ return false;
+ }
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => 'saved_settings'
+ );
+ break;
+ case 'get':
+ $domain = $_data;
+ if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ try {
+ return json_decode($redis->hGet('QW_BCC', $domain), true);
+ }
+ catch (RedisException $e) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => array('redis_error', $e)
+ );
+ return false;
+ }
+ break;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.rspamd.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.rspamd.inc.php
index b0ba1f5..bdc23b0 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.rspamd.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.rspamd.inc.php
@@ -137,7 +137,7 @@
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'log' => array(__FUNCTION__, $_action, '-'),
'msg' => 'access_denied'
);
return false;
@@ -148,7 +148,7 @@
if (!in_array($map, $rspamd_map_type)) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'log' => array(__FUNCTION__, $_action, '-'),
'msg' => array('global_map_invalid', $map)
);
continue;
@@ -170,14 +170,14 @@
catch (Exception $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'log' => array(__FUNCTION__, $_action, '-'),
'msg' => array('global_map_write_error', htmlspecialchars($map), htmlspecialchars($e->getMessage()))
);
continue;
}
$_SESSION['return'][] = array(
'type' => 'success',
- 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'log' => array(__FUNCTION__, $_action, '-'),
'msg' => array('object_modified', htmlspecialchars($map))
);
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.transports.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.transports.inc.php
index 7d8031a..7b22917 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.transports.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.transports.inc.php
@@ -1,7 +1,7 @@
<?php
function relayhost($_action, $_data = null) {
- global $pdo;
- global $lang;
+ global $pdo;
+ global $lang;
$_data_log = $_data;
switch ($_action) {
case 'add':
@@ -45,7 +45,7 @@
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => array('relayhost_added', htmlspecialchars(implode(', ', $hosts)))
+ 'msg' => array('relayhost_added', htmlspecialchars(implode(', ', (array)$hosts)))
);
break;
case 'edit':
@@ -100,7 +100,7 @@
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => array('object_modified', htmlspecialchars(implode(', ', $hostnames)))
+ 'msg' => array('object_modified', htmlspecialchars(implode(', ', (array)$hostnames)))
);
}
break;
@@ -137,11 +137,11 @@
}
break;
case 'get':
- if ($_SESSION['mailcow_cc_role'] != "admin") {
+ if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
return false;
}
$relayhosts = array();
- $stmt = $pdo->query("SELECT `id`, `hostname`, `username` FROM `relayhosts`");
+ $stmt = $pdo->query("SELECT `id`, `hostname`, `username`, `active` FROM `relayhosts`");
$relayhosts = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $relayhosts;
break;
@@ -166,14 +166,19 @@
$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;
+ $stmt = $pdo->prepare("SELECT GROUP_CONCAT(`username` SEPARATOR ', ') AS `used_by_mailboxes` FROM `mailbox` WHERE JSON_VALUE(`attributes`, '$.relayhost') = :id");
+ $stmt->execute(array(':id' => $_data));
+ $used_by_mailboxes = $stmt->fetch(PDO::FETCH_ASSOC)['used_by_mailboxes'];
+ $used_by_mailboxes = (empty($used_by_mailboxes)) ? '' : $used_by_mailboxes;
+ $relayhostdata['used_by_mailboxes'] = $used_by_mailboxes;
}
return $relayhostdata;
break;
}
}
function transport($_action, $_data = null) {
- global $pdo;
- global $lang;
+ global $pdo;
+ global $lang;
$_data_log = $_data;
switch ($_action) {
case 'add':
@@ -187,7 +192,7 @@
}
$destinations = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['destination']));
$active = intval($_data['active']);
- $lookup_mx = intval($_data['lookup_mx']);
+ $is_mx_based = intval($_data['is_mx_based']);
$nexthop = trim($_data['nexthop']);
if (filter_var($nexthop, FILTER_VALIDATE_IP)) {
$nexthop = '[' . $nexthop . ']';
@@ -233,7 +238,16 @@
continue;
}
// ".domain" is a valid destination, "..domain" is not
- if (empty($dest) || (is_valid_domain_name(preg_replace('/^' . preg_quote('.', '/') . '/', '', $dest)) === false && $dest != '*' && filter_var($dest, FILTER_VALIDATE_EMAIL) === false)) {
+ if ($is_mx_based == 0 && (empty($dest) || (is_valid_domain_name(preg_replace('/^' . preg_quote('.', '/') . '/', '', $dest)) === false && $dest != '*' && filter_var($dest, FILTER_VALIDATE_EMAIL) === false))) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => array('invalid_destination', $dest)
+ );
+ unset($destinations[$d_ix]);
+ continue;
+ }
+ if ($is_mx_based == 1 && (empty($dest) || @preg_match('/' . $dest . '/', null) === false)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
@@ -270,14 +284,14 @@
}
}
foreach ($destinations as $insert_dest) {
- $stmt = $pdo->prepare("INSERT INTO `transports` (`nexthop`, `destination`, `username` , `password`, `lookup_mx`, `active`)
- VALUES (:nexthop, :destination, :username, :password, :lookup_mx, :active)");
+ $stmt = $pdo->prepare("INSERT INTO `transports` (`nexthop`, `destination`, `is_mx_based`, `username` , `password`, `active`)
+ VALUES (:nexthop, :destination, :is_mx_based, :username, :password, :active)");
$stmt->execute(array(
':nexthop' => $nexthop,
':destination' => $insert_dest,
+ ':is_mx_based' => $is_mx_based,
':username' => $username,
':password' => str_replace(':', '\:', $password),
- ':lookup_mx' => $lookup_mx,
':active' => $active
));
}
@@ -293,7 +307,7 @@
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => array('relayhost_added', htmlspecialchars(implode(', ', $hosts)))
+ 'msg' => array('relayhost_added', htmlspecialchars(implode(', ', (array)$hosts)))
);
break;
case 'edit':
@@ -313,7 +327,7 @@
$nexthop = (!empty($_data['nexthop'])) ? trim($_data['nexthop']) : $is_now['nexthop'];
$username = (isset($_data['username'])) ? trim($_data['username']) : $is_now['username'];
$password = (isset($_data['password'])) ? trim($_data['password']) : $is_now['password'];
- $lookup_mx = (isset($_data['lookup_mx']) && $_data['lookup_mx'] != '') ? intval($_data['lookup_mx']) : $is_now['lookup_mx'];
+ $is_mx_based = (isset($_data['is_mx_based']) && $_data['is_mx_based'] != '') ? intval($_data['is_mx_based']) : $is_now['is_mx_based'];
$active = (isset($_data['active']) && $_data['active'] != '') ? intval($_data['active']) : $is_now['active'];
}
else {
@@ -348,6 +362,22 @@
}
}
}
+ if ($is_mx_based == 0 && (empty($destination) || (is_valid_domain_name(preg_replace('/^' . preg_quote('.', '/') . '/', '', $destination)) === false && $destination != '*' && filter_var($destination, FILTER_VALIDATE_EMAIL) === false))) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => array('invalid_destination', $destination)
+ );
+ return false;
+ }
+ if ($is_mx_based == 1 && (empty($destination) || @preg_match('/' . $destination . '/', null) === false)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_data_log),
+ 'msg' => array('invalid_destination', $destination)
+ );
+ return false;
+ }
if (isset($next_hop_matches[1])) {
if (in_array($next_hop_clean, $existing_nh)) {
$_SESSION['return'][] = array(
@@ -376,19 +406,19 @@
try {
$stmt = $pdo->prepare("UPDATE `transports` SET
`destination` = :destination,
+ `is_mx_based` = :is_mx_based,
`nexthop` = :nexthop,
`username` = :username,
`password` = :password,
- `lookup_mx` = :lookup_mx,
`active` = :active
WHERE `id` = :id");
$stmt->execute(array(
':id' => $id,
':destination' => $destination,
+ ':is_mx_based' => $is_mx_based,
':nexthop' => $nexthop,
':username' => $username,
':password' => $password,
- ':lookup_mx' => $lookup_mx,
':active' => $active
));
$stmt = $pdo->prepare("UPDATE `transports` SET
@@ -412,7 +442,7 @@
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
- 'msg' => array('object_modified', htmlspecialchars(implode(', ', $hostnames)))
+ 'msg' => array('object_modified', htmlspecialchars(implode(', ', (array)$hostnames)))
);
}
break;
@@ -451,7 +481,7 @@
return false;
}
$transports = array();
- $stmt = $pdo->query("SELECT `id`, `destination`, `nexthop`, `username` FROM `transports`");
+ $stmt = $pdo->query("SELECT `id`, `is_mx_based`, `destination`, `nexthop`, `username` FROM `transports`");
$transports = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $transports;
break;
@@ -461,12 +491,12 @@
}
$transportdata = array();
$stmt = $pdo->prepare("SELECT `id`,
+ `is_mx_based`,
`destination`,
`nexthop`,
`username`,
`password`,
`active`,
- `lookup_mx`,
CONCAT(LEFT(`password`, 3), '...') AS `password_short`
FROM `transports`
WHERE `id` = :id");
@@ -475,4 +505,4 @@
return $transportdata;
break;
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/header.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/header.inc.php
index d2add25..d97a388 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/header.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/header.inc.php
@@ -62,12 +62,12 @@
if (isset($_SESSION['mailcow_locale'])) {
?>
<li class="dropdown<?=(isset($_SESSION['mailcow_locale']) && count($AVAILABLE_LANGUAGES) === 1) ? ' lang-link-disabled"' : '' ?>">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><span class="lang-sm lang-lbl" lang="<?= $_SESSION['mailcow_locale']; ?>"></span><span class="caret"></span></a>
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><span class="flag-icon flag-icon-<?= $_SESSION['mailcow_locale']; ?>"></span><span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<?php
- foreach ($AVAILABLE_LANGUAGES as $language) {
+ foreach ($AVAILABLE_LANGUAGES as $c => $v) {
?>
- <li<?= ($_SESSION['mailcow_locale'] == $language) ? ' class="active"' : ''; ?>><a href="?<?= http_build_query(array_merge($_GET, array('lang' => $language))); ?>"><span class="lang-xs lang-lbl-full" lang="<?= $language; ?>"></span></a></li>
+ <li<?= ($_SESSION['mailcow_locale'] == $c) ? ' class="active"' : ''; ?>><a href="?<?= http_build_query(array_merge($_GET, array('lang' => $c))); ?>"><span class="flag-icon flag-icon-<?=$c;?>"></span> <?=$v;?></a></li>
<?php
}
?>
@@ -100,17 +100,17 @@
</ul>
</li>
<?php if (isset($_SESSION['mailcow_cc_role'])) { ?>
- <li<?= (preg_match("/quarantine/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/quarantine"><span class="glyphicon glyphicon-briefcase"></span> <?= $lang['header']['quarantine']; ?></a></li>
+ <li<?= (preg_match("/quarantine/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/quarantine"><i class="bi bi-inbox-fill"></i> <?= $lang['header']['quarantine']; ?></a></li>
<?php } if ($_SESSION['mailcow_cc_role'] == 'admin' && getenv('SKIP_SOGO') != "y") { ?>
- <li><a href data-toggle="modal" data-container="sogo-mailcow" data-target="#RestartContainer"><span class="glyphicon glyphicon-refresh"></span> <?= $lang['header']['restart_sogo']; ?></a></li>
+ <li><a href data-toggle="modal" data-container="sogo-mailcow" data-target="#RestartContainer"><i class="bi bi-arrow-repeat"></i> <?= $lang['header']['restart_sogo']; ?></a></li>
<?php } ?>
<li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><span class="glyphicon glyphicon-link"></span> <?= $lang['header']['apps']; ?> <span class="caret"></span></a>
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="bi bi-link-45deg"></i> <?=$UI_TEXTS['apps_name'];?> <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<?php foreach ($MAILCOW_APPS as $app) {
if (getenv('SKIP_SOGO') == "y" && preg_match('/^\/SOGo/i', $app['link'])) { continue; }
?>
- <li title="<?= htmlspecialchars($app['description']); ?>"><a href="<?= htmlspecialchars($app['link']); ?>"><?= htmlspecialchars($app['name']); ?></a></li>
+ <li title="<?=(isset($app['description'])) ? htmlspecialchars($app['description']) : '';?>"><a href="<?=(isset($app['link'])) ? htmlspecialchars($app['link']) : '';?>"><?=(isset($app['name'])) ? htmlspecialchars($app['name']) : '';?></a></li>
<?php
}
$app_links = customize('get', 'app_links');
@@ -127,9 +127,9 @@
</ul>
</li>
<?php } if (!isset($_SESSION['dual-login']) && isset($_SESSION['mailcow_cc_username'])) { ?>
- <li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?></b> <span class="glyphicon glyphicon-log-out"></span></a></li>
+ <li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?></b> <i class="bi bi-power"></i></a></li>
<?php } elseif (isset($_SESSION['dual-login'])) { ?>
- <li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?> <span class="text-info">(<?= htmlspecialchars($_SESSION['dual-login']['username']); ?>)</span> </b><span class="glyphicon glyphicon-log-out"></span></a></li>
+ <li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?> <span class="text-info">(<?= htmlspecialchars($_SESSION['dual-login']['username']); ?>)</span> </b><i class="bi bi-power"></i></a></li>
<?php } if (!preg_match('/y|yes/i', getenv('MASTER'))) { ?>
<li class="text-warning slave-info">[ slave ]</li>
<?php } ?>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/init_db.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/init_db.inc.php
index 8010bbd..c43afbf 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/init_db.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/init_db.inc.php
@@ -3,7 +3,7 @@
try {
global $pdo;
- $db_version = "28112020_1210";
+ $db_version = "01072021_0630";
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
@@ -152,9 +152,9 @@
"id" => "INT NOT NULL AUTO_INCREMENT",
"destination" => "VARCHAR(255) NOT NULL",
"nexthop" => "VARCHAR(255) NOT NULL",
- "username" => "VARCHAR(255) NOT NULL",
- "password" => "VARCHAR(255) NOT NULL",
- "lookup_mx" => "TINYINT(1) NOT NULL DEFAULT '1'",
+ "username" => "VARCHAR(255) NOT NULL DEFAULT ''",
+ "password" => "VARCHAR(255) NOT NULL DEFAULT ''",
+ "is_mx_based" => "TINYINT(1) NOT NULL DEFAULT '0'",
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
),
"keys" => array(
@@ -319,7 +319,8 @@
"" => array("username")
),
"key" => array(
- "domain" => array("domain")
+ "domain" => array("domain"),
+ "kind" => array("kind")
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
@@ -442,7 +443,9 @@
"cols" => array(
"address" => "VARCHAR(255) NOT NULL",
"goto" => "TEXT NOT NULL",
- "validity" => "INT(11) NOT NULL"
+ "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
+ "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
+ "validity" => "INT(11)"
),
"keys" => array(
"primary" => array(
@@ -505,6 +508,27 @@
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
+ "sasl_log" => array(
+ "cols" => array(
+ "service" => "VARCHAR(32) NOT NULL DEFAULT ''",
+ "app_password" => "INT",
+ "username" => "VARCHAR(255) NOT NULL",
+ "real_rip" => "VARCHAR(64) NOT NULL",
+ "datetime" => "DATETIME(0) NOT NULL DEFAULT NOW(0)"
+ ),
+ "keys" => array(
+ "primary" => array(
+ "" => array("service", "real_rip", "username")
+ ),
+ "key" => array(
+ "username" => array("username"),
+ "service" => array("service"),
+ "datetime" => array("datetime"),
+ "real_rip" => array("real_rip")
+ )
+ ),
+ "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
+ ),
"quota2" => array(
"cols" => array(
"username" => "VARCHAR(255) NOT NULL",
@@ -567,6 +591,8 @@
"protocol_access" => "TINYINT(1) NOT NULL DEFAULT '1'",
"smtp_ip_access" => "TINYINT(1) NOT NULL DEFAULT '1'",
"alias_domains" => "TINYINT(1) NOT NULL DEFAULT '0'",
+ "mailbox_relayhost" => "TINYINT(1) NOT NULL DEFAULT '1'",
+ "domain_relayhost" => "TINYINT(1) NOT NULL DEFAULT '1'",
"domain_desc" => "TINYINT(1) NOT NULL DEFAULT '0'"
),
"keys" => array(
@@ -972,6 +998,7 @@
}
}
}
+
// Migrate tls_enforce_* options
if ($table == 'mailbox') {
$stmt = $pdo->query("SHOW TABLES LIKE 'mailbox'");
@@ -988,6 +1015,7 @@
}
}
}
+
$stmt = $pdo->query("SHOW TABLES LIKE '" . $table . "'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results != 0) {
@@ -1179,6 +1207,8 @@
$pdo->query("UPDATE `pushover` SET `attributes` = JSON_SET(`attributes`, '$.only_x_prio', \"0\") WHERE JSON_VALUE(`attributes`, '$.only_x_prio') IS NULL;");
// mailbox
$pdo->query("UPDATE `mailbox` SET `attributes` = '{}' WHERE `attributes` = '' OR `attributes` IS NULL;");
+ $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.passwd_update', \"0\") WHERE JSON_VALUE(`attributes`, '$.passwd_update') IS NULL;");
+ $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.relayhost', \"0\") WHERE JSON_VALUE(`attributes`, '$.relayhost') IS NULL;");
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.force_pw_update', \"0\") WHERE JSON_VALUE(`attributes`, '$.force_pw_update') IS NULL;");
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.sogo_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.sogo_access') IS NULL;");
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.imap_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.imap_access') IS NULL;");
@@ -1226,6 +1256,7 @@
}
if (php_sapi_name() == "cli") {
include '/web/inc/vars.inc.php';
+ include '/web/inc/functions.docker.inc.php';
// $now = new DateTime();
// $mins = $now->getOffset() / 60;
// $sgn = ($mins < 0 ? -1 : 1);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates/bsi.pem b/mailcow/src/mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates/bsi.pem
new file mode 100644
index 0000000..2a6b40f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates/bsi.pem
Binary files differ
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates/trustkey.pem b/mailcow/src/mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates/trustkey.pem
new file mode 100644
index 0000000..f5a4df6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates/trustkey.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICpTCCAkqgAwIBAgIBATAKBggqhkjOPQQDAjCBrzELMAkGA1UEBhMCS1IxETAP
+BgNVBAgMCFNlb3VsLVNpMRMwEQYDVQQHDApHYW5nbmFtLUd1MRcwFQYDVQQKDA5l
+V0JNIENvLiwgTHRkLjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlv
+bjEcMBoGA1UEAwwTZVdCTSBDQSBDZXJ0aWZpY2F0ZTEdMBsGCSqGSIb3DQEJARYO
+aW5mb0BlLXdibS5jb20wHhcNMTgwNzAyMDUzMTM5WhcNMjMwNzAxMDUzMTM5WjCB
+rzELMAkGA1UEBhMCS1IxETAPBgNVBAgMCFNlb3VsLVNpMRMwEQYDVQQHDApHYW5n
+bmFtLUd1MRcwFQYDVQQKDA5lV0JNIENvLiwgTHRkLjEiMCAGA1UECwwZQXV0aGVu
+dGljYXRvciBBdHRlc3RhdGlvbjEcMBoGA1UEAwwTZVdCTSBDQSBDZXJ0aWZpY2F0
+ZTEdMBsGCSqGSIb3DQEJARYOaW5mb0BlLXdibS5jb20wWTATBgcqhkjOPQIBBggq
+hkjOPQMBBwNCAAQIfqHisi0oO/eyOqSaDrr9itG2IymBkHnSDGQIIYmT+vqA8AgO
+81momc2Ld5PGpEN6muE54wPHQjvc/yCih8u2o1UwUzASBgNVHRMBAf8ECDAGAQH/
+AgEAMB0GA1UdDgQWBBS3J/fxiAv22irdBs98SODhF7kU/jALBgNVHQ8EBAMCAQYw
+EQYJYIZIAYb4QgEBBAQDAgAHMAoGCCqGSM49BAMCA0kAMEYCIQDc41LFK4LJCBU2
+VVKIz7Z6sxPhUEkh8nLSLK6IXdkP5wIhAIeKVOZchaVO5aF7fbdXoSrcyy1YYeUe
+PLojcKI9fX84
+-----END CERTIFICATE-----
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/composer.json
index 17caa43..e7e6b68 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/composer.json
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/composer.json
@@ -3,11 +3,12 @@
"robthree/twofactorauth": "^1.6",
"yubico/u2flib-server": "^1.0",
"phpmailer/phpmailer": "^6.1",
- "php-mime-mail-parser/php-mime-mail-parser": "^5.0.5",
+ "php-mime-mail-parser/php-mime-mail-parser": "^7",
"soundasleep/html2text": "^0.5.0",
"ddeboer/imap": "^1.5",
"matthiasmullie/minify": "^1.3",
"bshaffer/oauth2-server-php": "^1.11",
- "mustangostang/spyc": "^0.6.3"
+ "mustangostang/spyc": "^0.6.3",
+ "directorytree/ldaprecord": "^2.4"
}
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/composer.lock b/mailcow/src/mailcow-dockerized/data/web/inc/lib/composer.lock
index b00a75d..e2633cc 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/composer.lock
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "58d5d30b266f8b8015d7937e1a35ac5d",
+ "content-hash": "50acd623ff29bb513cd29819f4537aa0",
"packages": [
{
"name": "bshaffer/oauth2-server-php",
@@ -70,31 +70,31 @@
},
{
"name": "ddeboer/imap",
- "version": "1.11.0",
+ "version": "1.12.1",
"source": {
"type": "git",
"url": "https://github.com/ddeboer/imap.git",
- "reference": "a089dfcb9d177f921eb5dadc8d4144a44dff22ee"
+ "reference": "dbed05ca67b93509345a820b2859de10c48948fb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ddeboer/imap/zipball/a089dfcb9d177f921eb5dadc8d4144a44dff22ee",
- "reference": "a089dfcb9d177f921eb5dadc8d4144a44dff22ee",
+ "url": "https://api.github.com/repos/ddeboer/imap/zipball/dbed05ca67b93509345a820b2859de10c48948fb",
+ "reference": "dbed05ca67b93509345a820b2859de10c48948fb",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"ext-imap": "*",
"ext-mbstring": "*",
- "php": "^7.3 || ^8.0"
+ "php": "^7.4 || ^8.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^2.16.7",
- "laminas/laminas-mail": "^2.12.3",
- "phpstan/phpstan": "^0.12.57",
- "phpstan/phpstan-phpunit": "^0.12.16",
- "phpstan/phpstan-strict-rules": "^0.12.5",
- "phpunit/phpunit": "^9.4.3"
+ "friendsofphp/php-cs-fixer": "^2.18.6",
+ "laminas/laminas-mail": "^2.14.0",
+ "phpstan/phpstan": "^0.12.84",
+ "phpstan/phpstan-phpunit": "^0.12.18",
+ "phpstan/phpstan-strict-rules": "^0.12.9",
+ "phpunit/phpunit": "^9.5.4"
},
"type": "library",
"autoload": {
@@ -128,7 +128,7 @@
],
"support": {
"issues": "https://github.com/ddeboer/imap/issues",
- "source": "https://github.com/ddeboer/imap/tree/1.11.0"
+ "source": "https://github.com/ddeboer/imap/tree/1.12.1"
},
"funding": [
{
@@ -140,20 +140,141 @@
"type": "github"
}
],
- "time": "2020-11-30T14:52:49+00:00"
+ "time": "2021-04-27T08:38:46+00:00"
},
{
- "name": "matthiasmullie/minify",
- "version": "1.3.65",
+ "name": "directorytree/ldaprecord",
+ "version": "v2.6.3",
"source": {
"type": "git",
- "url": "https://github.com/matthiasmullie/minify.git",
- "reference": "227f19062451c55a797e0cc667ef983834e6580c"
+ "url": "https://github.com/DirectoryTree/LdapRecord.git",
+ "reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/227f19062451c55a797e0cc667ef983834e6580c",
- "reference": "227f19062451c55a797e0cc667ef983834e6580c",
+ "url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
+ "reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-ldap": "*",
+ "illuminate/contracts": "^5.0|^6.0|^7.0|^8.0",
+ "nesbot/carbon": "^1.0|^2.0",
+ "php": ">=7.3",
+ "psr/log": "^1.0",
+ "psr/simple-cache": "^1.0",
+ "tightenco/collect": "^5.6|^6.0|^7.0|^8.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.0",
+ "phpunit/phpunit": "^8.0",
+ "spatie/ray": "^1.24"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "LdapRecord\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Steve Bauman",
+ "email": "steven_bauman@outlook.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "A fully-featured LDAP ORM.",
+ "homepage": "https://www.ldaprecord.com",
+ "keywords": [
+ "active directory",
+ "ad",
+ "adLDAP",
+ "adldap2",
+ "directory",
+ "ldap",
+ "ldaprecord",
+ "orm",
+ "windows"
+ ],
+ "support": {
+ "docs": "https://ldaprecord.com",
+ "email": "steven_bauman@outlook.com",
+ "issues": "https://github.com/DirectoryTree/LdapRecord/issues",
+ "source": "https://github.com/DirectoryTree/LdapRecord"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/stevebauman",
+ "type": "github"
+ }
+ ],
+ "time": "2021-08-05T21:52:43+00:00"
+ },
+ {
+ "name": "illuminate/contracts",
+ "version": "v8.53.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/illuminate/contracts.git",
+ "reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/illuminate/contracts/zipball/504a34286a1b4c5421c43087d6bd4e176138f6fb",
+ "reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.3|^8.0",
+ "psr/container": "^1.0",
+ "psr/simple-cache": "^1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "8.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Illuminate\\Contracts\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ }
+ ],
+ "description": "The Illuminate Contracts package.",
+ "homepage": "https://laravel.com",
+ "support": {
+ "issues": "https://github.com/laravel/framework/issues",
+ "source": "https://github.com/laravel/framework"
+ },
+ "time": "2021-08-03T14:03:47+00:00"
+ },
+ {
+ "name": "matthiasmullie/minify",
+ "version": "1.3.66",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/matthiasmullie/minify.git",
+ "reference": "45fd3b0f1dfa2c965857c6d4a470bea52adc31a6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/45fd3b0f1dfa2c965857c6d4a470bea52adc31a6",
+ "reference": "45fd3b0f1dfa2c965857c6d4a470bea52adc31a6",
"shasum": ""
},
"require": {
@@ -163,8 +284,8 @@
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2.0",
- "matthiasmullie/scrapbook": "~1.0",
- "phpunit/phpunit": "~4.8"
+ "matthiasmullie/scrapbook": "dev-master",
+ "phpunit/phpunit": ">=4.8"
},
"suggest": {
"psr/cache-implementation": "Cache implementation to use with Minify::cache"
@@ -202,7 +323,7 @@
],
"support": {
"issues": "https://github.com/matthiasmullie/minify/issues",
- "source": "https://github.com/matthiasmullie/minify/tree/1.3.65"
+ "source": "https://github.com/matthiasmullie/minify/tree/1.3.66"
},
"funding": [
{
@@ -218,7 +339,7 @@
"type": "github"
}
],
- "time": "2020-12-27T21:43:29+00:00"
+ "time": "2021-01-06T15:18:10+00:00"
},
{
"name": "matthiasmullie/path-converter",
@@ -324,6 +445,100 @@
"time": "2019-09-10T13:16:29+00:00"
},
{
+ "name": "nesbot/carbon",
+ "version": "2.51.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/briannesbitt/Carbon.git",
+ "reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
+ "reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": "^7.1.8 || ^8.0",
+ "symfony/polyfill-mbstring": "^1.0",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/translation": "^3.4 || ^4.0 || ^5.0"
+ },
+ "require-dev": {
+ "doctrine/orm": "^2.7",
+ "friendsofphp/php-cs-fixer": "^2.14 || ^3.0",
+ "kylekatarnls/multi-tester": "^2.0",
+ "phpmd/phpmd": "^2.9",
+ "phpstan/extension-installer": "^1.0",
+ "phpstan/phpstan": "^0.12.54",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.14",
+ "squizlabs/php_codesniffer": "^3.4"
+ },
+ "bin": [
+ "bin/carbon"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-3.x": "3.x-dev",
+ "dev-master": "2.x-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Carbon\\Laravel\\ServiceProvider"
+ ]
+ },
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Carbon\\": "src/Carbon/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Brian Nesbitt",
+ "email": "brian@nesbot.com",
+ "homepage": "https://markido.com"
+ },
+ {
+ "name": "kylekatarnls",
+ "homepage": "https://github.com/kylekatarnls"
+ }
+ ],
+ "description": "An API extension for DateTime that supports 281 different languages.",
+ "homepage": "https://carbon.nesbot.com",
+ "keywords": [
+ "date",
+ "datetime",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/briannesbitt/Carbon/issues",
+ "source": "https://github.com/briannesbitt/Carbon"
+ },
+ "funding": [
+ {
+ "url": "https://opencollective.com/Carbon",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-07-28T13:16:28+00:00"
+ },
+ {
"name": "paragonie/random_compat",
"version": "v9.99.100",
"source": {
@@ -375,31 +590,30 @@
},
{
"name": "php-mime-mail-parser/php-mime-mail-parser",
- "version": "5.0.5",
+ "version": "7.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-mime-mail-parser/php-mime-mail-parser.git",
- "reference": "27983433aabeccee832573c3c56e6a4855e57745"
+ "reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/27983433aabeccee832573c3c56e6a4855e57745",
- "reference": "27983433aabeccee832573c3c56e6a4855e57745",
+ "url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/9d09a017f3f103fec8456211a4a538b80e0eca0d",
+ "reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d",
"shasum": ""
},
"require": {
"ext-mailparse": "*",
- "php": "^7.1"
+ "php": "^7.2|^8.0"
},
"replace": {
"exorus/php-mime-mail-parser": "*",
"messaged/php-mime-mail-parser": "*"
},
"require-dev": {
- "php-coveralls/php-coveralls": "^2.1",
- "phpunit/php-token-stream": "^3.0",
- "phpunit/phpunit": "^7.0",
- "squizlabs/php_codesniffer": "^3.4"
+ "php-coveralls/php-coveralls": "^2.2",
+ "phpunit/phpunit": "^8.0",
+ "squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
"autoload": {
@@ -443,7 +657,7 @@
"role": "Developer"
}
],
- "description": "A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).",
+ "description": "A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).",
"homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
"keywords": [
"MimeMailParser",
@@ -455,22 +669,28 @@
],
"support": {
"issues": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/issues",
- "source": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/tree/master"
+ "source": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/tree/7.0.0"
},
- "time": "2019-09-23T11:57:58+00:00"
+ "funding": [
+ {
+ "url": "https://github.com/eXorus",
+ "type": "github"
+ }
+ ],
+ "time": "2021-02-25T17:21:57+00:00"
},
{
"name": "phpmailer/phpmailer",
- "version": "v6.2.0",
+ "version": "v6.5.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
- "reference": "e38888a75c070304ca5514197d4847a59a5c853f"
+ "reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e38888a75c070304ca5514197d4847a59a5c853f",
- "reference": "e38888a75c070304ca5514197d4847a59a5c853f",
+ "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a5b5c43e50b7fba655f793ad27303cd74c57363c",
+ "reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c",
"shasum": ""
},
"require": {
@@ -488,7 +708,7 @@
"yoast/phpunit-polyfills": "^0.2.0"
},
"suggest": {
- "ext-mbstring": "Needed to send email in multibyte encoding charset",
+ "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
"psr/log": "For optional PSR-3 debug logging",
@@ -525,7 +745,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
- "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.2.0"
+ "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.5.0"
},
"funding": [
{
@@ -533,28 +753,182 @@
"type": "github"
}
],
- "time": "2020-11-25T15:24:57+00:00"
+ "time": "2021-06-16T14:33:43+00:00"
},
{
- "name": "robthree/twofactorauth",
- "version": "1.7.0",
+ "name": "psr/container",
+ "version": "1.1.1",
"source": {
"type": "git",
- "url": "https://github.com/RobThree/TwoFactorAuth.git",
- "reference": "37983bf675c5baca09d19d6705170489d0df0002"
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/37983bf675c5baca09d19d6705170489d0df0002",
- "reference": "37983bf675c5baca09d19d6705170489d0df0002",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
+ "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/1.1.1"
+ },
+ "time": "2021-03-05T17:36:06+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/1.1.4"
+ },
+ "time": "2021-05-03T11:20:27+00:00"
+ },
+ {
+ "name": "psr/simple-cache",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for simple caching",
+ "keywords": [
+ "cache",
+ "caching",
+ "psr",
+ "psr-16",
+ "simple-cache"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/simple-cache/tree/master"
+ },
+ "time": "2017-10-23T01:57:42+00:00"
+ },
+ {
+ "name": "robthree/twofactorauth",
+ "version": "1.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/RobThree/TwoFactorAuth.git",
+ "reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/30a38627ae1e7c9399dae67e265063cd6ec5276c",
+ "reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c",
"shasum": ""
},
"require": {
"php": ">=5.6.0"
},
"require-dev": {
+ "php-parallel-lint/php-parallel-lint": "^1.2",
"phpunit/phpunit": "@stable"
},
+ "suggest": {
+ "bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider",
+ "endroid/qr-code": "Needed for EndroidQrCodeProvider"
+ },
"type": "library",
"autoload": {
"psr-4": {
@@ -588,7 +962,17 @@
"issues": "https://github.com/RobThree/TwoFactorAuth/issues",
"source": "https://github.com/RobThree/TwoFactorAuth"
},
- "time": "2020-01-02T19:56:46+00:00"
+ "funding": [
+ {
+ "url": "https://paypal.me/robiii",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/RobThree",
+ "type": "github"
+ }
+ ],
+ "time": "2021-03-09T18:24:05+00:00"
},
{
"name": "soundasleep/html2text",
@@ -646,6 +1030,551 @@
"time": "2017-04-19T22:01:50+00:00"
},
{
+ "name": "symfony/deprecation-contracts",
+ "version": "v2.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
+ "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-03-23T23:28:01+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.23.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
+ "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.23-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-05-27T12:26:48+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.23.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
+ "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.23-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ],
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-07-28T13:41:28+00:00"
+ },
+ {
+ "name": "symfony/translation",
+ "version": "v5.3.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation.git",
+ "reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
+ "reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/translation-contracts": "^2.3"
+ },
+ "conflict": {
+ "symfony/config": "<4.4",
+ "symfony/dependency-injection": "<5.0",
+ "symfony/http-kernel": "<5.0",
+ "symfony/twig-bundle": "<5.0",
+ "symfony/yaml": "<4.4"
+ },
+ "provide": {
+ "symfony/translation-implementation": "2.3"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^4.4|^5.0",
+ "symfony/console": "^4.4|^5.0",
+ "symfony/dependency-injection": "^5.0",
+ "symfony/finder": "^4.4|^5.0",
+ "symfony/http-kernel": "^5.0",
+ "symfony/intl": "^4.4|^5.0",
+ "symfony/polyfill-intl-icu": "^1.21",
+ "symfony/service-contracts": "^1.1.2|^2",
+ "symfony/yaml": "^4.4|^5.0"
+ },
+ "suggest": {
+ "psr/log-implementation": "To use logging capability in translator",
+ "symfony/config": "",
+ "symfony/yaml": ""
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\Translation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides tools to internationalize your application",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/translation/tree/v5.3.4"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-07-25T09:39:16+00:00"
+ },
+ {
+ "name": "symfony/translation-contracts",
+ "version": "v2.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation-contracts.git",
+ "reference": "95c812666f3e91db75385749fe219c5e494c7f95"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95",
+ "reference": "95c812666f3e91db75385749fe219c5e494c7f95",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5"
+ },
+ "suggest": {
+ "symfony/translation-implementation": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Translation\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to translation",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/translation-contracts/tree/v2.4.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-03-23T23:28:01+00:00"
+ },
+ {
+ "name": "symfony/var-dumper",
+ "version": "v5.3.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-dumper.git",
+ "reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
+ "reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<5.4.3",
+ "symfony/console": "<4.4"
+ },
+ "require-dev": {
+ "ext-iconv": "*",
+ "symfony/console": "^4.4|^5.0",
+ "symfony/process": "^4.4|^5.0",
+ "twig/twig": "^2.13|^3.0.4"
+ },
+ "suggest": {
+ "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
+ "ext-intl": "To show region name in time zone dump",
+ "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
+ },
+ "bin": [
+ "Resources/bin/var-dump-server"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions/dump.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\VarDumper\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides mechanisms for walking through any arbitrary PHP variable",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "debug",
+ "dump"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/var-dumper/tree/v5.3.6"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-07-27T01:56:02+00:00"
+ },
+ {
+ "name": "tightenco/collect",
+ "version": "v8.34.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/tighten/collect.git",
+ "reference": "b069783ab0c547bb894ebcf8e7f6024bb401f9d2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/tighten/collect/zipball/b069783ab0c547bb894ebcf8e7f6024bb401f9d2",
+ "reference": "b069783ab0c547bb894ebcf8e7f6024bb401f9d2",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2|^8.0",
+ "symfony/var-dumper": "^3.4 || ^4.0 || ^5.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.0",
+ "nesbot/carbon": "^2.23.0",
+ "phpunit/phpunit": "^8.3"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/Collect/Support/helpers.php",
+ "src/Collect/Support/alias.php"
+ ],
+ "psr-4": {
+ "Tightenco\\Collect\\": "src/Collect"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylorotwell@gmail.com"
+ }
+ ],
+ "description": "Collect - Illuminate Collections as a separate package.",
+ "keywords": [
+ "collection",
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/tighten/collect/issues",
+ "source": "https://github.com/tighten/collect/tree/v8.34.0"
+ },
+ "time": "2021-03-29T21:29:00+00:00"
+ },
+ {
"name": "yubico/u2flib-server",
"version": "1.0.2",
"source": {
@@ -695,5 +1624,5 @@
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
- "plugin-api-version": "2.0.0"
+ "plugin-api-version": "2.1.0"
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/sieve/extensions/vnd.dovecot.execute.xml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/sieve/extensions/vnd.dovecot.execute.xml
new file mode 100644
index 0000000..bce1ea9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/sieve/extensions/vnd.dovecot.execute.xml
@@ -0,0 +1,17 @@
+<?xml version='1.0' standalone='yes'?>
+
+<extension name="vnd.dovecot.execute">
+
+ <test name="execute">
+ <parameter type="tag" name="pipe" regex="pipe" occurrence="optional"/>
+ <parameter type="string" name="program-name"/>
+ <parameter type="stringlist" name="arguments" occurrence="optional"/>
+ </test>
+
+ <command name="execute">
+ <parameter type="tag" name="pipe" regex="pipe" occurrence="optional"/>
+ <parameter type="string" name="program-name"/>
+ <parameter type="stringlist" name="arguments" occurrence="optional"/>
+ </command>
+
+</extension>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/sieve/extensions/vnd.dovecot.filter.xml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/sieve/extensions/vnd.dovecot.filter.xml
new file mode 100644
index 0000000..45bf236
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/sieve/extensions/vnd.dovecot.filter.xml
@@ -0,0 +1,15 @@
+<?xml version='1.0' standalone='yes'?>
+
+<extension name="vnd.dovecot.filter">
+
+ <test name="filter">
+ <parameter type="string" name="program-name"/>
+ <parameter type="stringlist" name="arguments" occurrence="optional"/>
+ </test>
+
+ <command name="filter">
+ <parameter type="string" name="program-name"/>
+ <parameter type="stringlist" name="arguments" occurrence="optional"/>
+ </command>
+
+</extension>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/sieve/extensions/vnd.dovecot.pipe.xml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/sieve/extensions/vnd.dovecot.pipe.xml
new file mode 100644
index 0000000..6bbcfc3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/sieve/extensions/vnd.dovecot.pipe.xml
@@ -0,0 +1,11 @@
+<?xml version='1.0' standalone='yes'?>
+
+<extension name="vnd.dovecot.pipe">
+
+ <command name="pipe">
+ <parameter type="tag" name="try" regex="try" occurrence="optional"/>
+ <parameter type="string" name="program-name"/>
+ <parameter type="stringlist" name="arguments" occurrence="optional"/>
+ </command>
+
+</extension>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.gitattributes b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.gitattributes
new file mode 100644
index 0000000..84b904d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.gitattributes
@@ -0,0 +1,2 @@
+examples/ export-ignore
+tests/ export-ignore
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.github/issue_template.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.github/issue_template.md
new file mode 100644
index 0000000..f9aba6b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.github/issue_template.md
@@ -0,0 +1,10 @@
+- Adldap2 Version: #.#
+- LDAP Type: <!-- Active Directory / OpenLDAP / FreeIPA / Sun Directory Server? -->
+- PHP Version: #.#
+
+<!-- **ISSUES WITHOUT THE ABOVE INFORMATION WILL BE CLOSED!** -->
+
+### Description:
+
+
+### Steps To Reproduce:
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.gitignore b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.gitignore
new file mode 100644
index 0000000..2130d09
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.gitignore
@@ -0,0 +1,3 @@
+/.idea
+/vendor
+composer.lock
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.scrutinizer.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.scrutinizer.yml
new file mode 100644
index 0000000..9dbf8c1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.scrutinizer.yml
@@ -0,0 +1,10 @@
+filter:
+ excluded_paths:
+ - tests/*
+ - src/Schemas/*
+build:
+ nodes:
+ analysis:
+ tests:
+ override:
+ - command: php-scrutinizer-run
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.styleci.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.styleci.yml
new file mode 100644
index 0000000..8be488d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.styleci.yml
@@ -0,0 +1,7 @@
+preset: recommended
+
+enabled:
+ - length_ordered_imports
+
+disabled:
+ - alpha_ordered_imports
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.travis.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.travis.yml
new file mode 100644
index 0000000..2723d68
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/.travis.yml
@@ -0,0 +1,19 @@
+language: php
+
+php:
+ - 7.1
+ - 7.2
+ - 7.3
+ - 7.4
+
+before_script:
+ - travis_retry composer self-update
+ - travis_retry composer install --prefer-source --no-interaction
+
+script: ./vendor/bin/phpunit
+
+branches:
+ only:
+ - master
+ - v9.0
+ - v8.0
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/composer.json
new file mode 100644
index 0000000..26c1534
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/composer.json
@@ -0,0 +1,57 @@
+{
+ "name": "adldap2/adldap2",
+ "type": "library",
+ "description": "A PHP LDAP Package for humans.",
+ "keywords": [
+ "active directory",
+ "directory",
+ "ad",
+ "ldap",
+ "windows",
+ "adldap",
+ "adldap2"
+ ],
+ "license": "MIT",
+ "support": {
+ "docs": "https://github.com/Adldap2/Adldap2/blob/master/readme.md",
+ "issues": "https://github.com/Adldap2/Adldap2/issues",
+ "source": "https://github.com/Adldap2/Adldap2",
+ "email": "steven_bauman@outlook.com"
+ },
+ "authors": [
+ {
+ "name": "Steve Bauman",
+ "email": "steven_bauman@outlook.com",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "php": ">=7.0",
+ "ext-ldap": "*",
+ "ext-json": "*",
+ "psr/log": "~1.0",
+ "psr/simple-cache": "~1.0",
+ "tightenco/collect": "~5.0|~6.0|~7.0|~8.0",
+ "illuminate/contracts": "~5.0|~6.0|~7.0|~8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~6.0|~7.0|~8.0",
+ "mockery/mockery": "~1.0"
+ },
+ "suggest": {
+ "ext-fileinfo": "fileinfo is required when retrieving user encoded thumbnails"
+ },
+ "archive": {
+ "exclude": ["/examples", "/tests"]
+ },
+ "autoload": {
+ "psr-4": {
+ "Adldap\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Adldap\\Tests\\": "tests/"
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/phpunit.xml.tmppica b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/.nojekyll
similarity index 100%
rename from mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/phpunit.xml.tmppica
rename to mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/.nojekyll
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/_coverpage.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/_coverpage.md
new file mode 100644
index 0000000..fc8ec0b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/_coverpage.md
@@ -0,0 +1,16 @@
+<!-- _coverpage.md -->
+
+# Adldap2
+
+<p align="center">
+ <a href="https://travis-ci.org/Adldap2/Adldap2"><img src="https://img.shields.io/travis/Adldap2/Adldap2.svg?style=flat-square"/></a>
+ <a href="https://scrutinizer-ci.com/g/Adldap2/Adldap2/?branch=master"><img src="https://img.shields.io/scrutinizer/g/adLDAP2/adLDAP2/master.svg?style=flat-square"/></a>
+ <a href="https://packagist.org/packages/adldap2/adldap2"><img src="https://img.shields.io/packagist/dt/adldap2/adldap2.svg?style=flat-square"/></a>
+ <a href="https://packagist.org/packages/adldap2/adldap2"><img src="https://img.shields.io/packagist/v/adldap2/adldap2.svg?style=flat-square"/></a>
+ <a href="https://packagist.org/packages/adldap2/adldap2"><img src="https://img.shields.io/packagist/l/adldap2/adldap2.svg?style=flat-square"/></a>
+</p>
+
+> Working with LDAP doesn't need to be hard.
+
+<!-- background image -->
+![](media/bg.svg)
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/_sidebar.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/_sidebar.md
new file mode 100644
index 0000000..0284653
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/_sidebar.md
@@ -0,0 +1,27 @@
+<!-- _sidebar.md -->
+
+* Getting Started
+
+ * [Introduction](/)
+ * [Installation](installation.md)
+ * [Setup](setup.md)
+
+* Usage
+
+ * [Searching](searching.md)
+ * [Creating & Updating](models/model.md)
+ * [Events](events.md)
+ * [Logging](logging.md)
+ * [Working With Distiguished Names](distinguished-names.md)
+ * [Troubleshooting](troubleshooting.md)
+
+* Models
+ * [Model (Base)](models/model.md)
+ * [Computer](models/computer.md)
+ * [Contact](models/contact.md)
+ * [Container](models/container.md)
+ * [Group](models/group.md)
+ * [Organizational Unit](models/ou.md)
+ * [Printer](models/printer.md)
+ * [RootDse](models/root-dse.md)
+ * [User](models/user.md)
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/distinguished-names.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/distinguished-names.md
new file mode 100644
index 0000000..490b99b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/distinguished-names.md
@@ -0,0 +1,167 @@
+## Working With Distinguished Names
+
+Working with DN strings are a pain, but they're about to get easier. Adldap includes a DN builder for easily modifying and
+creating DN strings.
+
+> **Note**: All values inserted into DN methods are escaped. You do not need to escape **any** values before hand.
+
+#### Creating a New DN
+
+To create a new DN, construct a new `Adldap\Models\Attributes\DistinguishedName` instance:
+
+```php
+$dn = new Adldap\Models\Attributes\DistinguishedName();
+```
+
+You can also pass in a current DN string and start modifying it:
+
+```php
+$currentDn = 'cn=John Doe,ou=Accounting,dc=corp,dc=acme,dc=org';
+
+$dn = new Adldap\Models\Attributes\DistinguishedName($currentDn);
+```
+
+#### Adding / Removing a Domain Component
+
+```php
+// Add Domain Component
+$dn->addDc('corp');
+
+// Remove Domain Component
+$dn->removeDc('corp');
+```
+
+#### Adding / Removing an Organizational Unit
+
+```php
+// Add Organizational Unit
+$dn->addOu('Accounting');
+
+// Remove Organizational Unit
+$dn->removeOu('Accounting');
+```
+
+#### Adding / Removing Common Names
+
+```php
+// Add Common Name
+$dn->addCn('John Doe');
+
+// Remove Common Name
+$dn->removeCn('John Doe');
+```
+
+#### Setting a base
+
+If you'd like to set the base DN, such as a domain component RDN, use the `setBase()` method:
+
+```php
+$base = 'dc=corp,dc=acme,dc=org';
+
+$dn->setBase($base);
+```
+
+#### Creating a DN From A Model
+
+When you're creating a new LDAP record, you'll need to create a distinguished name as well. Let's go through an example of
+creating a new user.
+
+```php
+$user = $provider->make()->user();
+
+$user->setCommonName('John Doe');
+$user->setFirstName('John');
+$user->setLastName('Doe');
+```
+
+So we've set the basic information on the user, but we run into trouble when we want to put the user into a certain container
+(such as 'Accounting') which is done through the DN. Let's go through this example:
+
+```php
+$dn = $user->getDnBuilder();
+
+$dn->addCn($user->getCommonName());
+$dn->addOu('Accounting');
+$dn->addDc('corp');
+$dn->addDc('acme');
+$dn->addDc('org');
+
+// Returns 'cn=John Doe,ou=Accounting,dc=corp,dc=acme,dc=org'
+echo $dn->get();
+
+// The DistinguishedName object also contains the __toString() magic method
+// so you can also just echo the object itself
+echo $dn;
+```
+
+Now we've built a DN, and all we have to do is set it on the new user:
+
+```php
+$user->setDn($dn);
+
+$user->save();
+```
+
+#### Modifying a DN From A Model
+
+When you've received a model from a search result, you can build and modify the models DN like so:
+
+```php
+$user = $ad->users()->find('jdoe');
+
+$dn = $user->getDnBuilder();
+
+$dn->addOu('Users');
+
+$user->setDn($dn)->save();
+```
+
+#### Retrieving the RDN components
+
+To retrieve all of the RDN components of a Distinguished Name, call `getComponents()`:
+
+```php
+$dn = new Adldap\Models\Attributes\DistinguishedName(
+ 'cn=John Doe,ou=Accounting,dc=corp,dc=acme,dc=org'
+);
+
+$components = $dn->getComponents();
+
+var_dump($components);
+
+// Output:
+// array:5 [▼
+// "cn" => array:1 [▼
+// 0 => "John Doe"
+// ]
+// "uid" => []
+// "ou" => array:1 [▼
+// 0 => "Accounting"
+// ]
+// "dc" => array:3 [▼
+// 0 => "corp"
+// 1 => "acme"
+// 2 => "org"
+// ]
+// "o" => []
+// ]
+```
+
+You can also specify a component you would like returned by supplying it as an argument:
+
+```php
+$dn = new Adldap\Models\Attributes\DistinguishedName(
+ 'cn=John Doe,ou=Accounting,dc=corp,dc=acme,dc=org'
+);
+
+$dcs = $dn->getComponents('dc');
+
+var_dump($dcs);
+
+// Output:
+// array:3 [▼
+// 0 => "corp"
+// 1 => "acme"
+// 2 => "org"
+// ]
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/events.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/events.md
new file mode 100644
index 0000000..8175695
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/events.md
@@ -0,0 +1,175 @@
+# Events
+
+Adldap2 events provide a method of listening for certain LDAP actions
+that are called and execute tasks for that specific event.
+
+> **Note**: The Adldap2 event dispatcher was actually derived from the
+> [Laravel Framework](https://github.com/laravel/framework) with
+> Broadcasting & Queuing omitted to remove extra dependencies
+> that would be required with implementing those features.
+>
+> If you've utilized Laravel's events before, this will feel very familiar.
+
+## Registering Listeners
+
+> **Note**: Before we get to registering listeners, it's crucial to know that events throughout
+> Adldap2 are fired irrespective of the current connection or provider in use.
+>
+> This means that when using multiple LDAP connections, the same events will be fired.
+>
+> This allows you to set listeners on events that occur for all LDAP connections you utilize.
+>
+> If you are required to determine which events are fired from alternate connections, see [below](#determining-the-connection).
+
+To register a listener on an event, retrieve the event dispatcher and call the `listen()` method:
+
+```php
+use Adldap\Auth\Events\Binding;
+
+$dispatcher = \Adldap\Adldap::getEventDispatcher();
+
+$dispatcher->listen(Binding::class, function (Binding $event) {
+ // Do something with the Binding event information:
+
+ $event->connection; // Adldap\Connections\Ldap instance
+ $event->username; // 'jdoe@acme.org'
+ $event->password; // 'super-secret'
+});
+```
+
+The first argument is the event name you would like to listen for, and the
+second is either a closure or class name that should handle the event:
+
+Using a class:
+
+> **Note**: When using just a class name, the class must contain a public `handle()` method that will handle the event.
+
+```php
+use Adldap\Adldap;
+use Adldap\Auth\Events\Binding;
+
+$dispatcher = Adldap::getEventDispatcher();
+
+$dispatcher->listen(Binding::class, MyApp\BindingEventHandler::class);
+```
+
+```php
+namespace MyApp;
+
+use Adldap\Auth\Events\Binding;
+
+class BindingEventHandler
+{
+ public function handle(Binding $event)
+ {
+ // Handle the event...
+ }
+}
+```
+
+## Model Events
+
+Model events are handled the same way as authentication events.
+
+Simply call the event dispatcher `listen()` method with the model event you are wanting to listen for:
+
+```php
+use Adldap\Models\Events\Saving;
+
+$dispatcher = \Adldap\Adldap::getEventDispatcher();
+
+$dispatcher->listen(Saving::class, function (Saving $event) {
+ // Do something with the Saving event information:
+
+ // Returns the model instance being saved eg. `Adldap\Models\Entry`
+ $event->getModel();
+});
+```
+
+## Wildcard Event Listeners
+
+You can register listeners using the `*` as a wildcard parameter to catch multiple events with the same listener.
+
+Wildcard listeners will receive the event name as their first argument, and the entire event data array as their second argument:
+
+```php
+$dispatcher = Adldap::getEventDispatcher();
+
+// Listen for all model events.
+$dispatcher->listen('Adldap\Models\Events\*', function ($eventName, array $data) {
+ echo $eventName; // Returns 'Adldap\Models\Events\Updating'
+ var_dump($data); // Returns [0] => (object) Adldap\Models\Events\Updating;
+});
+
+$user = $provider->search()->users()->find('jdoe');
+
+$user->setTelephoneNumber('555 555-5555');
+
+$user->save();
+```
+
+## Determining the Connection
+
+If you're using multiple LDAP connections and you require the ability to determine which events belong
+to a certain connection, you can do so by verifying the host of the LDAP connection.
+
+Here's an example:
+
+```php
+$dispatcher = Adldap::getEventDispatcher();
+
+$dispatcher->listen(\Adldap\Models\Events\Creating::class, function ($event) {
+ $connection = $event->model->getConnection();
+
+ $host = $connection->getHost();
+
+ echo $host; // Displays 'ldap://192.168.1.1:386'
+});
+```
+
+Another example with auth events:
+
+```php
+$dispatcher = Adldap::getEventDispatcher();
+
+$dispatcher->listen(\Adldap\Auth\Events\Binding::class, function ($event) {
+ $connection = $event->connection;
+
+ $host = $connection->getHost();
+
+ echo $host; // Displays 'ldap://192.168.1.1:386'
+});
+```
+
+## List of Events
+
+### Authentication Events
+
+There are several events that are fired during initial and subsequent binds to your configured LDAP server.
+
+Here is a list of all events that are fired:
+
+| Event| Description |
+|---|---|
+| Adldap\Auth\Events\Attempting | When any authentication attempt is called via: `$provider->auth()->attempt()` |
+| Adldap\Auth\Events\Passed | When any authentication attempts pass via: `$provider->auth()->attempt()` |
+| Adldap\Auth\Events\Failed | When any authentication attempts fail via: `$provider->auth()->attempt()` *Or* `$provider->auth()->bind()` |
+| Adldap\Auth\Events\Binding | When any LDAP bind attempts occur via: `$provider->auth()->attempt()` *Or* `$provider->auth()->bind()` |
+| Adldap\Auth\Events\Bound | When any LDAP bind attempts are successful via: `$provider->auth()->attempt()` *Or* `$provider->auth()->bind()` |
+
+### Model Events
+
+There are several events that are fired during the creation, updating and deleting of all models.
+
+Here is a list of all events that are fired:
+
+| Event | Description |
+|---|---|
+| Adldap\Models\Events\Saving | When a model is in the process of being saved via: `$model->save()` |
+| Adldap\Models\Events\Saved | When a model has been successfully saved via: `$model->save()` |
+| Adldap\Models\Events\Creating | When a model is being created via: `$model->save()` *Or* `$model->create()` |
+| Adldap\Models\Events\Created | When a model has been successfully created via: `$model->save()` *Or* `$model->create()` |
+| Adldap\Models\Events\Updating | When a model is being updated via: `$model->save()` *Or* `$model->update()` |
+| Adldap\Models\Events\Updated | When a model has been successfully updated via: `$model->save()` *Or* `$model->update()` |
+| Adldap\Models\Events\Deleting | When a model is being deleted via: `$model->delete()` |
+| Adldap\Models\Events\Deleted | When a model has been successfully deleted via: `$model->delete()` |
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/index.html b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/index.html
new file mode 100644
index 0000000..adf939b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/index.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <title>Adldap2 Documentation</title>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta name="description" content="Adldap2 Documentation">
+ <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+ <link rel="stylesheet" href="https://unpkg.com/docsify/lib/themes/vue.css">
+ </head>
+
+ <body>
+ <div id="app"></div>
+
+ <script>
+ window.$docsify = {
+ name: 'Adldap2',
+ repo: 'https://github.com/Adldap2/Adldap2',
+ autoHeader: true,
+ auto2top: true,
+ homepage: 'readme.md',
+ coverpage: true,
+ search: 'auto',
+ loadSidebar: true,
+ subMaxLevel: 3
+ }
+ </script>
+
+
+ <script src="https://unpkg.com/docsify/lib/docsify.min.js"></script>
+ <script src="https://unpkg.com/prismjs/components/prism-php.min.js"></script>
+ <script src="https://unpkg.com/docsify/lib/plugins/search.min.js"></script>
+ </body>
+</html>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/installation.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/installation.md
new file mode 100644
index 0000000..de21239
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/installation.md
@@ -0,0 +1,29 @@
+# Requirements
+
+Adldap2 requires the following:
+
+- PHP 7.0 or greater
+- LDAP extension enabled in PHP
+- An LDAP server (ActiveDirectory, OpenLDAP, FreeIPA etc.)
+
+# Composer
+
+Adldap2 uses [Composer](https://getcomposer.org) for installation.
+
+Once you have composer installed, run the following command in the root directory of your project:
+
+```bash
+composer require adldap2/adldap2
+```
+
+Then, if your application doesn't already require Composer's autoload, you will need to do it manually.
+
+Insert this line at the top of your projects PHP script (usually `index.php`):
+
+```php
+require __DIR__ . '/vendor/autoload.php';
+```
+
+You're all set!
+
+Now, head over to the [setup guide](setup.md) to get up and running.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/logging.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/logging.md
new file mode 100644
index 0000000..b49bcd3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/logging.md
@@ -0,0 +1,74 @@
+# Logging
+
+Adldap2 includes an implementation of PSR's widely supported [Logger](https://github.com/php-fig/log) interface.
+
+By default, all of Adldap2's [events](events.md) will call the logger you have set to utilize.
+
+> **Note**: Adldap2 does not include a file / text logger. You must implement your own.
+
+## Registering & Enabling a Logger
+
+To register a logger call `Adldap::setLogger()`. The logger must implement the `Psr\Log\LoggerInterface`.
+
+>**Note**: Be sure to set the logger prior to creating a new `Adldap` instance. This
+> ensures all events throughout the lifecycle of the request use your logger.
+
+```php
+use Adldap\Adldap;
+
+Adldap::setLogger($myLogger);
+
+$config = ['...'];
+
+$ad = new Adldap();
+
+$ad->addProvider($config);
+```
+
+## Disabling Logging
+
+If you need to disable the event logger after a certain set of operations, simply pass in `null` and logging will be disabled:
+
+```php
+use Adldap\Adldap;
+
+Adldap::setLogger($myLogger);
+
+$config = ['...'];
+
+$ad = new Adldap();
+
+$ad->addProvider($config);
+
+try {
+ $ad->connect();
+
+ // Disable logging anything else.
+ Adldap::setLogger(null);
+} catch (\Adldap\Connections\BindException $e) {
+ //
+}
+```
+
+## Logged Information
+
+Here is a list of events that are logged along with the information included:
+
+| Authentication Events | Logged |
+|---|---|
+| `Adldap\Auth\Events\Attempting` | `LDAP (ldap://192.168.1.1:389) - Operation: Adldap\Auth\Events\Attempting - Username: CN=Steve Bauman,OU=Users,DC=corp,DC=acme,DC=org` |
+| `Adldap\Auth\Events\Binding` |` LDAP (ldap://192.168.1.1:389) - Operation: Adldap\Auth\Events\Binding - Username: CN=Steve Bauman,OU=Users,DC=corp,DC=acme,DC=org` |
+| `Adldap\Auth\Events\Bound` | `LDAP (ldap://192.168.1.1:389) - Operation: Adldap\Auth\Events\Bound - Username: CN=Steve Bauman,OU=Users,DC=corp,DC=acme,DC=org` |
+| `Adldap\Auth\Events\Passed` | `LDAP (ldap://192.168.1.1:389) - Operation: Adldap\Auth\Events\Passed - Username: CN=Steve Bauman,OU=Users,DC=corp,DC=acme,DC=org` |
+| `Adldap\Auth\Events\Failed` | `LDAP (ldap://192.168.1.1:389) - Operation: Adldap\Auth\Events\Failed - Username: CN=Steve Bauman,OU=Users,DC=corp,DC=acme,DC=org - Result: Invalid Credentials` |
+
+| Model Events | Logged |
+|---|---|
+| `Adldap\Models\Events\Saving` | `LDAP (ldap://192.168.1.1:389) - Operation: Saving - On: Adldap\Models\User - Distinguished Name: cn=John Doe,dc=acme,dc=org` |
+| `Adldap\Models\Events\Saved` | `LDAP (ldap://192.168.1.1:389) - Operation: Saved - On: Adldap\Models\User - Distinguished Name: cn=John Doe,dc=acme,dc=org` |
+| `Adldap\Models\Events\Creating` | `LDAP (ldap://192.168.1.1:389) - Operation: Creating - On: Adldap\Models\User - Distinguished Name: cn=John Doe,dc=acme,dc=org` |
+| `Adldap\Models\Events\Created` | `LDAP (ldap://192.168.1.1:389) - Operation: Created - On: Adldap\Models\User - Distinguished Name: cn=John Doe,dc=acme,dc=org` |
+| `Adldap\Models\Events\Updating` | `LDAP (ldap://192.168.1.1:389) - Operation: Updating - On: Adldap\Models\User - Distinguished Name: cn=John Doe,dc=acme,dc=org` |
+| `Adldap\Models\Events\Updated` | `LDAP (ldap://192.168.1.1:389) - Operation: Updated - On: Adldap\Models\User - Distinguished Name: cn=John Doe,dc=acme,dc=org` |
+| `Adldap\Models\Events\Deleting` | `LDAP (ldap://192.168.1.1:389) - Operation: Deleting - On: Adldap\Models\User - Distinguished Name: cn=John Doe,dc=acme,dc=org` |
+| `Adldap\Models\Events\Deleted` | `LDAP (ldap://192.168.1.1:389) - Operation: Deleted - On: Adldap\Models\User - Distinguished Name: cn=John Doe,dc=acme,dc=org` |
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/media/bg.svg b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/media/bg.svg
new file mode 100644
index 0000000..e70e863
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/media/bg.svg
@@ -0,0 +1 @@
+<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%' viewBox='0 0 1600 800'><rect fill='#46ff55' width='1600' height='800'/><g ><path fill='#51ff76' d='M486 705.8c-109.3-21.8-223.4-32.2-335.3-19.4C99.5 692.1 49 703 0 719.8V800h843.8c-115.9-33.2-230.8-68.1-347.6-92.2C492.8 707.1 489.4 706.5 486 705.8z'/><path fill='#57ff94' d='M1600 0H0v719.8c49-16.8 99.5-27.8 150.7-33.5c111.9-12.7 226-2.4 335.3 19.4c3.4 0.7 6.8 1.4 10.2 2c116.8 24 231.7 59 347.6 92.2H1600V0z'/><path fill='#5affb1' d='M478.4 581c3.2 0.8 6.4 1.7 9.5 2.5c196.2 52.5 388.7 133.5 593.5 176.6c174.2 36.6 349.5 29.2 518.6-10.2V0H0v574.9c52.3-17.6 106.5-27.7 161.1-30.9C268.4 537.4 375.7 554.2 478.4 581z'/><path fill='#57ffcd' d='M0 0v429.4c55.6-18.4 113.5-27.3 171.4-27.7c102.8-0.8 203.2 22.7 299.3 54.5c3 1 5.9 2 8.9 3c183.6 62 365.7 146.1 562.4 192.1c186.7 43.7 376.3 34.4 557.9-12.6V0H0z'/><path fill='#50ffe8' d='M181.8 259.4c98.2 6 191.9 35.2 281.3 72.1c2.8 1.1 5.5 2.3 8.3 3.4c171 71.6 342.7 158.5 531.3 207.7c198.8 51.8 403.4 40.8 597.3-14.8V0H0v283.2C59 263.6 120.6 255.7 181.8 259.4z'/><path fill='#7dffe9' d='M1600 0H0v136.3c62.3-20.9 127.7-27.5 192.2-19.2c93.6 12.1 180.5 47.7 263.3 89.6c2.6 1.3 5.1 2.6 7.7 3.9c158.4 81.1 319.7 170.9 500.3 223.2c210.5 61 430.8 49 636.6-16.6V0z'/><path fill='#9effe9' d='M454.9 86.3C600.7 177 751.6 269.3 924.1 325c208.6 67.4 431.3 60.8 637.9-5.3c12.8-4.1 25.4-8.4 38.1-12.9V0H288.1c56 21.3 108.7 50.6 159.7 82C450.2 83.4 452.5 84.9 454.9 86.3z'/><path fill='#baffea' d='M1600 0H498c118.1 85.8 243.5 164.5 386.8 216.2c191.8 69.2 400 74.7 595 21.1c40.8-11.2 81.1-25.2 120.3-41.7V0z'/><path fill='#d2ffea' d='M1397.5 154.8c47.2-10.6 93.6-25.3 138.6-43.8c21.7-8.9 43-18.8 63.9-29.5V0H643.4c62.9 41.7 129.7 78.2 202.1 107.4C1020.4 178.1 1214.2 196.1 1397.5 154.8z'/><path fill='#e9ffeb' d='M1315.3 72.4c75.3-12.6 148.9-37.1 216.8-72.4h-723C966.8 71 1144.7 101 1315.3 72.4z'/></g></svg>
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/computer.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/computer.md
new file mode 100644
index 0000000..e3057ab
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/computer.md
@@ -0,0 +1,32 @@
+# The Computer Model
+
+> **Note**: This model contains the traits `HasDescription`, `HasLastLogonAndLogOff` & `HasCriticalSystemObject`.
+> For more information, visit the documentation:
+>
+> [HasDescription](/models/traits/has-description.md),
+> [HasLastLogonAndLogOff](/models/traits/has-last-login-last-logoff.md),
+> [HasCriticalSystemObject](/models/traits/has-critical-system-object.md)
+
+## Methods
+
+```php
+$computer = $provider->search()->computers()->find('ACME-EXCHANGE');
+
+// Returns 'Windows Server 2003'
+$computer->getOperatingSystem();
+
+// Returns '5.2 (3790)';
+$computer->getOperatingSystemVersion();
+
+// Returns 'Service Pack 1';
+$computer->getOperatingSystemServicePack();
+
+// Returns 'ACME-DESKTOP001.corp.acme.org'
+$computer->getDnsHostName();
+
+$computer->getLastLogOff();
+
+$computer->getLastLogon();
+
+$computer->getLastLogonTimestamp();
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/contact.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/contact.md
new file mode 100644
index 0000000..e42c8f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/contact.md
@@ -0,0 +1,13 @@
+# The Contact Model
+
+The Contact model extends from the base `Adldap\Models\Model` class and contains
+no specific methods / attributes that are limited to it.
+
+## Creation
+
+```php
+// Adldap\Models\Contact
+$contact = $provider->make()->contact([
+ 'cn' => 'Suzy Doe',
+]);
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/container.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/container.md
new file mode 100644
index 0000000..132b549
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/container.md
@@ -0,0 +1,24 @@
+# The Container Model
+
+> **Note**: This model contains the trait `HasDescription` & `HasCriticalSystemObject`.
+> For more information, visit the documentation:
+>
+> [HasDescription](/models/traits/has-description.md),
+> [HasCriticalSystemObject](/models/traits/has-critical-system-object.md),
+
+## Creation
+
+```php
+// Adldap\Models\Container
+$container = $provider->make()->container([
+ 'cn' => 'VPN Users',
+]);
+```
+
+## Methods
+
+The `Container` model contains only one unique method.
+
+```php
+$flags = $container->getSystemFlags();
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/group.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/group.md
new file mode 100644
index 0000000..cf7c6d4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/group.md
@@ -0,0 +1,253 @@
+# The Group Model
+
+> **Note**: This model contains the trait `HasMemberOf`.
+> For more information, visit the documentation:
+>
+> [HasMemberOf](/models/traits/has-member-of.md)
+
+## Creation
+
+```php
+// Adldap\Models\Group
+$group = $provider->make()->group([
+ 'cn' => 'Managers',
+]);
+
+// Create group's DN through the DN Builder:
+$group = $provider->make()->group();
+
+$dn = $group->getDnBuilder();
+
+$dn->addOu('Workstation Computers');
+
+$dn->addCn("Managers");
+
+$group->setDn($dn);
+
+// Or set the DN manually:
+$ou->setDn('cn=Managers,ou=Workstation Computers,dc=test,dc=local,dc=com');
+
+$group->save();
+```
+
+## Getting a groups members
+
+When you receive a `Group` model instance, it will contain a `member`
+attribute which contains the distinguished names of all
+the members inside the group.
+
+```php
+$group = $provider->search()->groups()->first();
+
+foreach ($group->members as $member) {
+ echo $member; // 'cn=John Doe,dc=corp,dc=acme,dc=org'
+}
+```
+
+But this might not be useful, since we might actually want the models for each member.
+
+This can be easily done with the `getMembers()` method on the group.
+
+```php
+$group = $provider->search()->groups()->first();
+
+foreach ($group->getMembers() as $member) {
+ echo get_class($member); // Instance of `Adldap\Models\Model`
+
+ echo $member->getCommonName();
+}
+```
+
+> **Note**: You should be aware however, that calling the `getMembers()` method will
+> query your `AD` server for **every** member contained in the group to retrieve
+> its model. For larger group sets it may be worth paginating them.
+
+
+### Paginating Group Members
+
+The group you're looking for might contain hundreds / thousands of members.
+
+In this case, your server might only return you a portion of the groups members.
+
+To get around this limit, you need to ask your server to paginate the groups members through a select:
+
+```php
+$group = $provider->search()->groups()->select('member;range=0-500')->first();
+
+foreach ($group->members as $member) {
+ // We'll only have 500 members in this query.
+}
+```
+
+Now, when we have the group instance, we'll only have the first `500` members inside this group.
+However, calling the `getMembers()` method will automatically retrieve the rest of the members for you:
+
+```php
+$group = $provider->search()->groups()->select('member;range=0-500')->first();
+
+foreach ($group->getMembers() as $member) {
+ // Adldap will automatically retrieve the next 500
+ // records until it's retrieved all records.
+ $member->getCommonName();
+}
+```
+
+> **Note**: Groups containing large amounts of users (1000+) will require
+> more memory assigned to PHP. Your mileage will vary.
+
+#### Paginating large sets of Group Members
+
+When requesting group members from groups that contain a large amount of members
+(typically over 1000), you may receive PHP memory limit errors due to
+the large amount of the objects being created in the request.
+
+To resolve this, you will need to retrieve the members manually. However using
+this route you will only be able to retrieve the members distinguished names.
+
+```php
+$from = 0;
+$to = 500;
+$range = "member;range=$from-$to";
+
+// Retrieve the group.
+$group = $provider->search()->select($range)->raw()->find('Accounting');
+
+// Remove the count from the member array.
+unset($group[$range]['count']);
+
+// The array of group members distinguished names.
+$members = $group[$range];
+
+foreach ($members as $member) {
+ echo $member; // 'cn=John Doe,dc=acme,dc=org'
+}
+```
+
+You can then encapsulate the above example into a recursive function to retrieve the remaining group members.
+
+## Getting only a groups member names
+
+To retrieve only the names of the members contained in a group, call the `getMemberNames()` method:
+
+```php
+foreach ($group->getMemberNames() as $name) {
+ // Returns 'John Doe'
+ echo $name;
+}
+```
+
+> **Note**: This method does not query your server for each member to retrieve its name. It
+> only parses the distinguished names from the groups `member` attribute. This means that
+> if you have paginated group members, you will need to perform another query yourself
+> to retrieve the rest of the member names (or just call the `getMembers()` method).
+
+## Setting Group Members
+
+To set members that are apart of the group, you can perform this in two ways:
+
+> **Note**: Remember, this will remove **all** pre-existing members, and set the new given members on the group.
+
+```php
+$members = [
+ 'cn=John Doe,dc=corp,dc=acme,dc=org',
+ 'cn=Jane Doe,dc=corp,dc=acme,dc=org',
+];
+
+$group->setMembers($members);
+
+$group->save();
+```
+
+Or manually:
+
+```php
+$group->member = [
+ 'cn=John Doe,dc=corp,dc=acme,dc=org',
+ 'cn=Jane Doe,dc=corp,dc=acme,dc=org',
+];
+
+$group->save();
+```
+
+## Adding One Member
+
+To add a single member to a group, use the `addMember()` method:
+
+> **Note**: You do not need to call the `save()` method after adding a
+> member. It's automatically called so you can determine
+> if the member was successfully added.
+
+```php
+// We can provide a model, or just a plain DN of the new member
+$user = $provider->search()->users()->first();
+
+if ($group->addMember($user)) {
+ // User was successfully added to the group!
+}
+
+// Or
+
+$user = 'cn=John Doe,dc=corp,dc=acme,dc=org';
+
+if ($group->addMember($user)) {
+ //
+}
+```
+
+## Adding Multiple Group Members
+
+To add multiple members to a group, use the `addMembers()` method:
+
+> **Note**: You do not need to call the `save()` method after adding
+> members. It's automatically called so you can determine
+> if the members were successfully added.
+
+```php
+$members = [
+ 'cn=John Doe,dc=corp,dc=acme,dc=org',
+ 'cn=Jane Doe,dc=corp,dc=acme,dc=org',
+];
+
+$group->addMembers($members);
+
+// Or
+
+$user = $provider->search()->users()->first();
+
+if ($group->addMembers($user)) {
+ //
+}
+```
+
+## Removing One Member
+
+To remove a single member to a group, use the `removeMember()` method:
+
+```php
+// We can provide a model, or just a plain DN of the existing member
+$group = $provider->search()->groups()->first();
+
+$member = $group->getMembers()->first();
+
+if ($group->removeMember($member)) {
+ // Member was successfully removed from the group!
+}
+
+// Or
+
+$user = 'cn=John Doe,dc=corp,dc=acme,dc=org';
+
+if ($group->removeMember($user)) {
+ //
+}
+```
+
+## Removing All Members
+
+To remove all members, use the `removeMembers()` method:
+
+```php
+if ($group->removeMembers()) {
+ // All members were successfully removed!
+}
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/model.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/model.md
new file mode 100644
index 0000000..fbcecc8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/model.md
@@ -0,0 +1,655 @@
+# Creating / Updating
+
+## Introduction
+
+Adldap2 implements the [ActiveRecord](https://en.wikipedia.org/wiki/Active_record_pattern) pattern.
+This means that each LDAP record in your directory is represented as it's own model instance.
+
+## Creating
+
+Creating LDAP entries manually is always a pain, but Adldap2 makes it effortless. Let's get started.
+
+When you have a provider instance, call the `make()` method. This returns an `Adldap\Models\Factory` instance:
+
+```php
+$factory = $provider->make();
+```
+
+Or you can chain all methods if you'd prefer:
+
+```php
+$user = $provider->make()->user();
+```
+
+### Available Make Methods
+
+When calling a make method, all of them accept an `$attributes` parameter
+to fill the model with your specified attributes.
+
+```php
+// Adldap\Models\User
+$user = $provider->make()->user([
+ 'cn' => 'John Doe',
+]);
+
+// Adldap\Models\Computer
+$computer = $provider->make()->computer([
+ 'cn' => 'COMP-101',
+]);
+
+// Adldap\Models\Contact
+$contact = $provider->make()->contact([
+ 'cn' => 'Suzy Doe',
+]);
+
+// Adldap\Models\Container
+$container = $provider->make()->container([
+ 'cn' => 'VPN Users',
+]);
+
+// Adldap\Models\Group
+$group = $provider->make()->group([
+ 'cn' => 'Managers',
+]);
+
+// Adldap\Models\OrganizationalUnit
+$ou = $provider->make()->ou([
+ 'name' => 'Acme',
+]);
+```
+
+## Saving
+
+When you have any model instance, you can call the `save()` method to persist the
+changes to your server. This method returns a `boolean`. For example:
+
+```php
+$user = $provider->make()->user([
+ 'cn' => 'New User',
+]);
+
+if ($user->save()) {
+ // User was saved.
+} else {
+ // There was an issue saving this user.
+}
+```
+
+> **Note**: When a model is saved successfully (whether created or updated), the
+> models attributes are re-synced in the background from your LDAP server.
+>
+> This allows you to perform other operations during the same
+> request that require an existing model.
+
+### Creating (Manually)
+
+If you are sure the model **does not exist** already inside your LDAP directory, you can use the `create()` method:
+
+```php
+$user = $provider->make()->user([
+ 'cn' => 'New User',
+]);
+
+if ($user->create()) {
+ // User was created.
+} else {
+ // There was an issue creating this user.
+}
+```
+
+> **Note**: When you call the create method, if the model does not have a
+> distinguished name, one will automatically be generated for you using your
+> `base_dn` set in your configuration and the models common name.
+
+### Updating (Manually)
+
+If you are sure the model **does exist** already inside your LDAP directory, you can use the `update()` method:
+
+```php
+$user = $provider->search()->whereEquals('cn', 'John Doe')->firstOrFail();
+
+$user->displayName = 'Suzy Doe';
+
+if ($user->update()) {
+ // User was updated.
+} else {
+ // There was an issue updating this user.
+}
+```
+
+## Checking Existence
+
+If you need to check the existence of a model, use the property `exists`.
+
+How does it know if the model exists in your LDAP directory? Well, when models are constructed from
+search results, the `exists` property on the model is set to `true`.
+
+```php
+$user = $provider->search()->find('jdoe');
+
+$user->exists; // Returns true.
+
+if ($user->delete()) {
+ $user->exists; // Returns false.
+}
+```
+
+If a model is created successfully, the `exists` property is set to `true`:
+
+```php
+$user = $provider->make()->user([
+ 'cn' => 'John Doe',
+]);
+
+$user->exists; // Returns false.
+
+if ($user->save()) {
+ $user->exists; // Returns true.
+}
+```
+
+## Attributes
+
+Due to LDAPs multi-valued nature, all LDAP attributes inside a model have their own array.
+
+For example, a models attributes may contain the following:
+
+```php
+var_dump($user->getAttributes());
+
+// Returns:
+/*
+[
+ 'cn' => [
+ 0 => 'John Doe',
+ ],
+ 'sn' => [
+ 0 => 'Doe',
+ ],
+ 'givenname' => [
+ 0 => 'John'
+ ],
+ 'useraccountcontrol' => [
+ 0 => 512
+ ],
+ 'mail' => [
+ 0 => 'jdoe@acme.org',
+ 1 => 'john-doe@acme.org',
+ ],
+ 'memberof' => [
+ 0 => 'cn=Accountants,ou=Groups,dc=acme,dc=org',
+ 1 => 'cn=Employees,ou=Groups,dc=acme,dc=org',
+ 2 => 'cn=Users,ou=Groups,dc=acme,dc=org',
+ ],
+]
+*/
+```
+
+You can notice in the above dumped array that each attribute contains
+its own array with a value assigned to the first key.
+
+Since all models extend from the base class `Adldap\Models\Model`, there
+are many useful methods that you can use on every model to easily
+retrieve these attributes you're looking for.
+
+### Getting Attributes
+
+You can get attributes in a few ways:
+
+```php
+// Returns an array all of the users attributes.
+$user->getAttributes();
+
+// Returns an array of all the users email addresses.
+// Returns `null` if non-existent.
+$user->getAttribute('mail');
+
+// Returns the users first email address.
+// Returns `null` if non-existent.
+$user->getAttribute('mail', 0);
+
+// Returns the users first email address.
+// Returns `null` if non-existent.
+$user->getFirstAttribute('mail');
+
+// Returns an array of all the users email addresses.
+$user->mail;
+
+// Returns the users first email address.
+$user->mail[0];
+```
+
+#### Using a Getter
+
+Some attributes have methods for easier retrieval so you don't need to look up the LDAP attribute name.
+
+For example, to retrieve a users email address, use the method `getEmail()`:
+
+```php
+$user->getEmail();
+```
+
+##### Other Methods
+
+The following methods are available on all returned models:
+
+```php
+// Returns the model's 'name' attribute.
+$model->getName();
+
+// Returns the model's 'cn' attribute.
+$model->getCommonName();
+
+// Returns the model's 'displayname' attribute.
+$model->getDisplayName();
+
+// Returns the model's 'samaccountname' attriubte.
+$model->getAccountName();
+
+// Returns the model's 'samaccounttype` attribute.
+$model->getAccountType();
+
+// Returns the model's 'whencreated` attribute.
+$model->getCreatedAt();
+
+// Returns the model's 'whencreated` attribute in a MySQL timestamp format.
+$model->getCreatedAtDate();
+
+// Returns the model's 'whencreated' attribute in unix time.
+$model->getCreatedAtTimestamp();
+
+// Returns the model's 'whenchanged` attribute.
+$model->getUpdatedAt();
+
+// Returns the model's 'whenchanged` attribute in a MySQL timestamp format.
+$model->getUpdatedAtDate();
+
+// Returns the model's 'whenchanged` attribute in unix time.
+$model->getUpdatedAtTimestamp();
+
+// Returns the model's 'objectclass' attribute.
+$model->getObjectClass();
+
+// Returns the model's root object category string.
+$model->getObjectCategory();
+
+// Returns the model's object category in an array.
+$model->getObjectCategoryArray();
+
+// Returns the model's object category distinguished name.
+$model->getObjectCategoryDn();
+
+// Returns the model's SID in binary.
+$model->getObjectSid();
+
+// Returns the model's GUID in binary.
+$model->getObjectGuid();
+
+// Returns the model's SID in a string.
+$model->getConvertedSid();
+
+// Returns the model's GUID in a string.
+$model->getConvertedGuid();
+
+// Returns the model's primary group ID.
+$model->getPrimaryGroupId();
+
+// Returns the model's 'instancetype' attribute.
+$model->getInstanceType();
+
+// Returns the model's 'maxpwdage' attribute.
+$model->getMaxPasswordAge();
+```
+
+For more documentation on specific getters, please take a look at the relevant model documentation.
+
+#### Getting Dirty (Modified) Attributes
+
+You can get a models modified attributes using the `getDirty()` method:
+
+```php
+$user = $provider->search()->users()->find('john');
+
+// Returns array [0 => 'John Doe']
+var_dump($user->cn);
+
+$user->setAttribute('cn', 'Jane Doe');
+
+// Returns array ['cn' => [0 => 'Jane Doe']]
+var_dump($user->getDirty());
+
+// The attribute has been modified - returns array [0 => 'Jane Doe']
+var_dump($user->cn);
+```
+
+The method returns an array with the key being the modified attribute,
+and the array being the new values of the attribute.
+
+#### Getting Original (Unmodified) Attributes
+
+You can get a models original attributes using the `getOriginal()` method:
+
+```php
+$user = $provider->search()->users()->find('john');
+
+// Returns array [0 => 'John Doe']
+var_dump($user->cn);
+
+$user->setAttribute('cn', 'Jane Doe');
+
+// The attribute has been modified - returns array [0 => 'Jane Doe']
+var_dump($user->cn);
+
+// Retrieving the original value - returns array [0 => 'John Doe']
+var_dump($user->getOriginal()['cn']);
+```
+
+> **Note**: Keep in mind, when you `save()` a model, the models original
+> attributes will be re-synchronized to the models new attributes.
+
+### Setting Attributes
+
+Just like getting model attributes, there's multiple ways of setting attributes as well:
+
+```php
+// Setting via method:
+$user->setAttribute('cn', 'John Doe');
+
+// Specifying a subkey for overwriting specific attributes:
+$user->setAttribute('mail', 'other-mail@mail.com', 0);
+
+// Setting the first attribute:
+$user->setFirstAttribute('mail', 'jdoe@mail.com');
+
+// Setting via property:
+$user->cn = 'John Doe';
+
+// Mass setting attributes:
+$user->fill([
+ 'cn' => 'John Doe',
+ 'mail' => 'jdoe@mail.com',
+]);
+```
+
+#### Setting Boolean Attributes
+
+When setting boolean attribute values, you cannot use `0` / `1` / `true` / `false` as these
+are simply converted to integer values when saving and your LDAP server will
+likely return an error for doing so on certain attributes.
+
+You will need to use the string versions of the boolean (`'TRUE'` / `'FALSE'`) for the
+boolean attribute to be set properly on your LDAP server.
+
+Here's an example:
+
+```php
+$user->setFirstAttribute('msExchHideFromAddressLists', 'TRUE');
+
+$user->save();
+```
+
+### Creating Attributes
+
+To create an attribute that does not exist on the model, you can set it like a regular property:
+
+```php
+$user = $provider->search()->whereEquals('cn', 'John Doe')->firstOrFail();
+
+$user->new = 'New Attribute';
+
+$user->save();
+```
+
+If the set attribute does not exist on the model already,
+it will automatically be created when you call the `save()` method.
+
+If you'd like manually create new attributes individually, call the `createAttribute($attribute, $value)` method:
+
+```php
+if ($user->createAttribute('new', 'New Attribute')) {
+ // Attribute created.
+}
+```
+
+### Updating Attributes
+
+To modify an attribute you can either use a setter method, or by setting it manually:
+
+> **Note**: You can also utilize setters to create new attributes if your model does not already have the attribute.
+
+```php
+$user = $provider->search()->whereEquals('cn', 'John Doe')->firstOrFail();
+
+$user->cn = 'New Name';
+
+// Or use a setter:
+
+$user->setCommonName('New Name');
+
+$user->save();
+```
+
+If you'd like to update attributes individually, call the `updateAttribute($attribute, $value)` method:
+
+```php
+if ($user->updateAttribute('cn', 'New Name')) {
+ // Successfully updated attribute.
+}
+```
+
+### Removing Attributes
+
+To remove attributes, set the attribute to `NULL`:
+
+```php
+$user->cn = null;
+
+$user->save();
+```
+
+Or, you can call the `deleteAttribute($attribute)` method:
+
+```php
+if ($user->deleteAttribute('cn')) {
+ // Attribute has been deleted.
+}
+```
+
+### Checking Attributes
+
+#### Checking Existence of Attributes
+
+To see if a model contains an attribute, use the method `hasAttribute()`:
+
+```php
+// Checking if a base attribute exists:
+if ($user->hasAttribute('mail')) {
+ // This user contains an email address.
+}
+
+// Checking if a sub attribute exists, by key:
+if ($user->hasAttribute('mail', 1)) {
+ // This user contains a second email address.
+}
+```
+
+#### Counting the Models Attributes
+
+To retrieve the total number of attributes, use the method `countAttributes()`:
+
+```php
+$count = $user->countAttributes();
+
+var_dump($count); // Returns int
+```
+
+#### Checking if a Model is contained in an OU
+
+To check if a model is located inside an OU, use the `inOu()` method:
+
+```php
+if ($model->inOu('User Accounts')) {
+ // This model is inside the 'User Accounts' OU.
+}
+```
+
+You can also use an OU model instance:
+
+```php
+$serviceAccounts = $provider->search()->ous()->find('Service Accounts');
+
+if ($model->inOu($serviceAccounts)) {
+ // This model is inside the 'Service Accounts' OU.
+}
+```
+
+#### Checking if a Model is Writable
+
+To check if the model can be written to, use the method `isWritable()`:
+
+```php
+if ($model->isWritable()) {
+ // You can modify this model.
+}
+```
+
+### Force Re-Syncing A Models Attributes
+
+If you need to forcefully re-sync a models attributes, use the method `syncRaw()`:
+
+```php
+$user->syncRaw();
+```
+
+> **Note**: This will query your LDAP server for the current model, and re-synchronize
+> it's attributes. This is only recommended if your creating / updating / deleting
+> attributes manually through your LDAP connection.
+
+## Moving / Renaming
+
+To move a user from one DN or OU to another, use the `move()` method:
+
+> **Note**: The `move()` method is actually an alias for the `rename()` method.
+
+```php
+// New parent distiguished name.
+$newParentDn = 'OU=New Ou,DC=corp,DC=local';
+
+if ($user->move($newParentDn)) {
+ // User was successfully moved to the new OU.
+}
+```
+
+You can also provide a model to move the child model into:
+
+```php
+// New parent OU.
+$newParentOu = $provider->search()->ous()->find('Accounting');
+
+if ($user->move($newParentOu)) {
+ // User was successfully moved to the new OU.
+}
+```
+
+If you would like to keep the models old RDN along side their new RDN, pass in false in the second parameter:
+
+```php
+// New parent distiguished name.
+$newParentDn = 'OU=New Ou,DC=corp,DC=local';
+
+if ($user->move($newParentDn, $deleteOldRdn = false)) {
+ // User was successfully moved to the new OU,
+ // and their old RDN has been left in-tact.
+}
+```
+
+To rename a users DN, just pass in their new relative distinguished name in the `rename()` method:
+
+```php
+$newRdn = 'cn=New Name';
+
+if ($user->rename($newRdn)) {
+ // User was successfully renamed.
+}
+```
+
+## Deleting
+
+To delete a model, just call the `delete()` method:
+
+```php
+$user = $provider->search()->whereEquals('cn', 'John Doe')->firstOrFail();
+
+echo $user->exists; // Returns true.
+
+if ($user->delete()) {
+ // Successfully deleted user.
+
+ echo $user->exists; // Returns false.
+}
+```
+
+## Extending
+
+> **Note**: This feature was introduced in `v8.0.0`.
+
+To use your own models, you will need to create a new [Schema](../schema.md).
+
+Once you have created your own schema, you must insert it inside the construct of your provider.
+
+Let's walk through this process.
+
+First we'll create our model we'd like to extend / override:
+
+> **Note**: Your custom model **must** extend from an existing Adldap2 model.
+> This is due to methods and attributes that only exist on these classes.
+
+```php
+namespace App\Ldap\Models;
+
+use Adldap\Models\User as Model;
+
+class User extends Model
+{
+ public function getCommonName()
+ {
+ // Overriding model method.
+ }
+}
+```
+
+Now, we'll create our custom schema and return our models class name:
+
+```php
+namespace App\Ldap\Schemas;
+
+use App\Ldap\Models\User;
+
+class LdapSchema extends ActiveDirectory
+{
+ public function userModel()
+ {
+ return User::class;
+ }
+}
+```
+
+Finally, when we create a provider, we need to insert our Schema into the configuration:
+
+```php
+$config = [
+ 'hosts' => ['...'],
+
+ 'username' => 'admin',
+ 'password' => 'P@ssword',
+
+ 'schema' => MyApp\LdapSchema::class,
+];
+
+$ad = new Adldap($config);
+
+$provider = $ad->connect();
+
+// If `jdoe` exists, your custom model will be returned.
+$user = $provider->search()->users()->find('jdoe');
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/organization.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/organization.md
new file mode 100644
index 0000000..57c00e3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/organization.md
@@ -0,0 +1,19 @@
+# The Organization Model
+
+The Organization model extends from the base `Adldap\Models\Model` class and contains
+no specific methods / attributes that are limited to it.
+
+## Creation
+
+```php
+// Adldap\Models\Organization
+$org = $provider->make()->organization([
+ 'o' => 'Some Company',
+]);
+
+// Set the DN manually:
+
+$org->setDn('o=Some Company,dc=test,dc=local,dc=com');
+
+$org->save();
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/ou.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/ou.md
new file mode 100644
index 0000000..ec473b1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/ou.md
@@ -0,0 +1,27 @@
+# The OrganizationalUnit Model
+
+The OrganizationalUnit model extends from the base `Adldap\Models\Model` class and contains
+no specific methods / attributes that are limited to it.
+
+## Creation
+
+```php
+// Adldap\Models\OrganizationalUnit
+$ou = $provider->make()->ou([
+ 'name' => 'Workstation Computers',
+]);
+
+// Generate the OU's DN through the DN Builder:
+
+$dn = $ou->getDnBuilder();
+
+$dn->addOu('Workstation Computers');
+
+$ou->setDn($dn);
+
+// Or set the DN manually:
+
+$ou->setDn('ou=Workstation Computers,dc=test,dc=local,dc=com');
+
+$ou->save();
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/printer.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/printer.md
new file mode 100644
index 0000000..4adc666
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/printer.md
@@ -0,0 +1,49 @@
+# The Printer Model
+
+## Methods
+
+```php
+$printer->getPrinterName();
+
+$printer->getPrinterShareName();
+
+$printer->getMemory();
+
+$printer->getUrl();
+
+$printer->getLocation();
+
+$printer->getServerName();
+
+$printer->getColorSupported();
+
+$printer->getDuplexSupported();
+
+$printer->getMediaSupported();
+
+$printer->getStaplingSupported();
+
+$printer->getPrintBinNames();
+
+$printer->getPrintMaxResolution();
+
+$printer->getPrintOrientations();
+
+$printer->getDriverName();
+
+$printer->getDriverVersion();
+
+$printer->getPriority();
+
+$printer->getPrintStartTime();
+
+$printer->getPrintEndTime();
+
+$printer->getPortName();
+
+$printer->getVersionNumber();
+
+$printer->getPrintRate();
+
+$printer->getPrintRateUnit();
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/root-dse.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/root-dse.md
new file mode 100644
index 0000000..e798c0e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/root-dse.md
@@ -0,0 +1,33 @@
+# The RootDse Model
+
+## Getting the Root DSE
+
+To get the Root DSE of your LDAP server, call the `getRootDse()` method off a new search:
+
+```php
+$rootDse = $provider->search()->getRootDse();
+```
+
+## Getting the schema naming context
+
+To get the Root DSE schema naming context, call the `getSchemaNamingContext()`:
+
+```php
+$rootDse = $provider->search()->getRootDse();
+
+$context = $rootDse->getSchemaNamingContext();
+
+// Returns 'cn=Schema,cn=Configuration,dc=corp,dc=acme,dc=org'
+echo $context;
+```
+
+## Getting the root domain naming context
+
+To get the Root DSE domain naming context, call the `getRootDomainNamingContext()`:
+
+```php
+$context = $rootDse->getRootDomainNamingContext();
+
+// Returns 'dc=corp,dc=acme,dc=org'
+echo $context;
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-critical-system-object.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-critical-system-object.md
new file mode 100644
index 0000000..095acad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-critical-system-object.md
@@ -0,0 +1,13 @@
+# HasCriticalSystemObject Trait
+
+Models that contain this trait, have the `isCriticalSystemObject` attribute.
+
+There is only one method that accompanies this trait:
+
+```php
+if ($model->isCriticalSystemObject()) {
+
+ //
+
+}
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-description.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-description.md
new file mode 100644
index 0000000..5c26d02
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-description.md
@@ -0,0 +1,11 @@
+# HasDescription Trait
+
+Models that contain this trait, have the `description` attribute.
+
+There are only two methods that accompany this trait:
+
+```php
+$model->getDescription();
+
+$model->setDescription('The models description');
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-last-login-last-logoff.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-last-login-last-logoff.md
new file mode 100644
index 0000000..76078c5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-last-login-last-logoff.md
@@ -0,0 +1,16 @@
+# HasLastLoginAndLastLogoff Trait
+
+Models that contain this trait have the `lastlogoff`, `lastlogon` and `lastlogontimestamp` attributes.
+
+## Methods
+
+```php
+// Returns the models's last log off attribute.
+$computer->getLastLogOff();
+
+// Returns the models's last log on attribute.
+$computer->getLastLogon();
+
+// Returns the models's last log on timestamp attribute.
+$computer->getLastLogonTimestamp();
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-member-of.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-member-of.md
new file mode 100644
index 0000000..d3063df
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/traits/has-member-of.md
@@ -0,0 +1,166 @@
+# HasMemberOf Trait
+
+Models that contain this trait, have the ability to be apart of a group.
+
+There's many helpful methods to assist you in all of the operations related to group membership, let's get started!
+
+## Retrieving Groups
+
+To retrieve the groups that a model is apart of, call the `getGroups()` method:
+
+```php
+$user = $provider->search()->users()->find('jdoe');
+
+$groups = $user->getGroups();
+
+foreach ($groups as $group) {
+
+ $group->getCommonName(); // ex. 'Accounting'
+
+}
+```
+
+We can also pass in specific fields we need from the returned groups to speed up our queries.
+
+For example, if we only need the groups common name:
+
+```php
+// Group models will be returned with only their common name.
+$groups = $user->getGroups(['cn']);
+```
+
+However, calling `getGroups()` will only retrieve the models immediate groups (non-recursive).
+
+To retrieve nested groups, pass in `true` into the second parameter:
+
+```php
+$groups = $user->getGroups([], $recursive = true);
+```
+
+## Retrieve Group Names
+
+If you only want the models group names, call the `getGroupNames()` method:
+
+```php
+$names = $user->getGroupNames();
+
+foreach ($names as $name) {
+
+ echo $name; // ex. 'Accounting'
+
+}
+```
+
+However, this method will also retrieve only the immediate groups names
+much like the `getGroups()` method. You'll need to pass in `true` in
+the first parameter to retrieve results recursively.
+
+```php
+$names = $user->getGroupNames($recursive = true);
+```
+
+## Checking if the Model is apart of a Group
+
+To check if a model is apart of a certain group, use the `inGroup()` method:
+
+```php
+$group = $provider->search()->groups()->find('Office');
+
+if ($user->inGroup($group)) {
+
+ //
+
+}
+```
+
+You can also check for multiple memberships by passing in an array of groups:
+
+```php
+$groups = $provider->search()->findManyBy('cn', ['Accounting', 'Office']));
+
+if ($user->inGroup($groups->toArray()) {
+
+ // This user is apart of the 'Accounting' and 'Office' group!
+
+}
+```
+
+> **Note**: Much like the other methods above, you'll need to provide a `$recursive`
+> flag to the `inGroup()` method if you'd like recursive results included.
+
+We can also provide distinguished names instead of Group model instances:
+
+```php
+$dns = [
+ 'cn=Accounting,ou=Groups,dc=acme,dc=org',
+ 'cn=Office,ou=Groups,dc=acme,dc=org',
+];
+
+if ($user->inGroup($dns, $recursive = true)) {
+
+ //
+
+}
+```
+
+Or, we can also just provide the name(s) of the group(s).
+
+```php
+$names = [
+ 'Accounting',
+ 'Office',
+];
+
+if ($user->inGroup($names, $recursive = true)) {
+
+ //
+
+}
+```
+
+## Adding a Group
+
+To add the model to a specific group, call the `addGroup()` method:
+
+```php
+$group = $provider->search()->groups()->find('Accounting');
+
+// You can either provide a Group model:
+if ($user->addGroup($group)) {
+
+ //
+
+}
+
+// Or a Groups DN:
+if ($user->addGroup('cn=Accounting,ou=Groups,dc=acme,dc=org')) {
+
+ //
+
+}
+```
+
+> **Note**: You do not need to call the `save()` method for adding / removing groups.
+> This is done automatically so you can perform clean `if` statements on the method.
+
+## Removing a Group
+
+To remove the model from a specific group, call the `removeGroup()` method:
+
+```php
+$group = $user->getGroups()->first();
+
+// You can either provide a Group model:
+if ($user->removeGroup($group)) {
+
+ //
+
+}
+
+// Or the groups DN:
+if ($user->removeGroup('cn=Accounting,ou=Office Groups,dc=acme,dc=org')) {
+
+ //
+
+}
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/user.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/user.md
new file mode 100644
index 0000000..65576e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/models/user.md
@@ -0,0 +1,180 @@
+# The User Model
+
+> **Note**: This model contains the trait `HasMemberOf`. For more information, visit the documentation:
+> [HasMemberOfTrait](/models/traits/has-member-of.md)
+
+## Creating
+
+> **Note**: If you need to create users with passwords, SSL or TLS **must** be enabled on your configured connection.
+>
+> The password you enter for the user **must** also obey your LDAP servers password requirements,
+> otherwise you will receive a "Server is unwilling to perform" LDAP exception upon saving.
+
+```php
+// Construct a new User model instance.
+$user = $provider->make()->user();
+
+// Create the users distinguished name.
+// We're adding an OU onto the users base DN to have it be saved in the specified OU.
+$dn = $user->getDnBuilder()->addOu('Users'); // Built DN will be: "CN=John Doe,OU=Users,DC=acme,DC=org";
+
+// Set the users DN, account name.
+$user->setDn($dn);
+$user->setAccountName('jdoe');
+$user->setCommonName('John Doe');
+
+// Set the users password.
+// NOTE: This password must obey your AD servers password requirements
+// (including password history, length, special characters etc.)
+// otherwise saving will fail and you will receive an
+// "LDAP Server is unwilling to perform" message.
+$user->setPassword('correct-horse-battery-staple');
+
+// Get a new account control object for the user.
+$ac = $user->getUserAccountControlObject();
+
+// Mark the account as enabled (normal).
+$ac->accountIsNormal();
+
+// Set the account control on the user and save it.
+$user->setUserAccountControl($ac);
+
+// Save the user.
+$user->save();
+
+// All done! An enabled user will be created and is ready for use.
+```
+
+## Methods
+
+There's a ton of available methods for the User model. Below is a list for a quick reference.
+
+> **Note**: Don't see a method for an LDAP attribute? Create an issue and let us know!
+
+```php
+// Get the users display name.
+$user->getDisplayName();
+
+// Get the users first email address.
+$user->getEmail();
+
+// Get the users title.
+$user->getTitle();
+
+// Get the users department.
+$user->getDepartment();
+
+// Get the users first name.
+$user->getFirstName();
+
+// Get the users last name.
+$user->getLastName();
+
+// Get the users info.
+$user->getInfo();
+
+// Get the users initials.
+$user->getInitials();
+
+// Get the users country.
+$user->getCountry();
+
+// Get the users street address.
+$user->getStreetAddress();
+
+// Get the users postal code.
+$user->getPostalCode();
+
+// Get the users physical delivery office name.
+$user->getPhysicalDeliveryOfficeName();
+
+// Get the users phone number.
+$user->getTelephoneNumber();
+
+// Get the users locale.
+$user->getLocale();
+
+// Get the users company.
+$user->getCompany();
+
+// Get the users other email addresses.
+$user->getOtherMailbox();
+
+// Get the users home mailbox database location (stored as a distinguished name).
+$user->getHomeMdb();
+
+// Get the users email nickname.
+$user->getMailNickname();
+
+// Get the users principal name.
+$user->getUserPrincipalName();
+
+// Get the users proxy email addresses.
+$user->getProxyAddresses();
+
+// Get the users failed login attempts.
+$user->getBadPasswordCount();
+
+// Get the users last failed login attempt timestamp.
+$user->getBadPasswordTime();
+
+// Get the users last password change timestamp.
+$user->getPasswordLastSet();
+
+// Get the users last password change timestamp in unix time.
+$user->getPasswordLastSetTimestamp();
+
+// Get the users last password change timestamp in MySQL date format.
+$user->getPasswordLastSetDate();
+
+// Get the users lockout time.
+$user->getLockoutTime();
+
+// Get the users user account control integer.
+$user->getUserAccountControl();
+
+// Get the users roaming profile path.
+$user->getProfilePath();
+
+// Get the users legacy exchange distinguished name.
+$user->getLegacyExchangeDn();
+
+// Get the users account expiry timestamp.
+$user->getAccountExpiry();
+
+// Get the boolean that determines whether to show this user in the global address book.
+$user->getShowInAddressBook();
+
+// Get the users thumbnail photo.
+$user->getThumbnail();
+
+// Get the users thumbnail photo (base64 encoded for HTML <img src=""> tags).
+$user->getThumbnailEncoded();
+
+// Get the users jpeg photo.
+$user->getJpegPhoto();
+
+// Get the users jpeg photo (base64 encoded for HTML <img src=""> tags).
+$user->getJpegPhotoEncoded();
+
+// Get the users manager.
+$user->getManager();
+
+// Get the users employee ID.
+$user->getEmployeeId();
+
+// Get the users employee number.
+$user->getEmployeeNumber();
+
+// Get the users employee type
+$user->getEmployeeType();
+
+// Get the users room number.
+$user->getRoomNumber();
+
+// Get the users department number.
+$user->getDepartmentNumber();
+
+// Get the users personal title.
+$user->getPersonalTitle();
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/readme.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/readme.md
new file mode 100644
index 0000000..00eaab7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/readme.md
@@ -0,0 +1,115 @@
+# Introduction
+
+## What is Adldap2?
+
+Adldap2 is a PHP LDAP package that allows you to:
+
+1. Easily manage multiple LDAP connections at once
+2. Perform authentication
+3. Search your LDAP directory with a fluent and easy to use query builder
+4. Create / Update / Delete LDAP entities with ease
+5. And more
+
+## History of Adldap2
+
+Adldap2 was originally created as a fork of the original LDAP library [adLDAP](https://github.com/adldap/adLDAP) due to bugs, and it being completely abandoned.
+
+Adldap2 contains absolutely no similarities to the original repository, and was built to be as easily accessible as possible, with great documentation, and easily understandable syntax.
+
+Much of the API was constructed with Ruby's ActiveRecord and Laravel's Eloquent in mind, and to be an answer to the question:
+
+> _Why can't we use LDAP like we use a database?_
+
+## Why should you use Adldap2?
+
+Working with LDAP in PHP can be a messy and confusing endeavor, especially when using multiple connections, creating and managing entities, performing moves, resetting passwords, and performing ACL modifications to user accounts.
+
+Wrapper classes for LDAP are usually always created in PHP applications.
+
+Adldap2 allows you to easily manage the above problems without reinventing the wheel for every project.
+
+## Implementations
+
+- [Laravel](https://github.com/Adldap2/Adldap2-Laravel)
+
+## Quick Start
+
+Install the package via `composer`:
+
+```
+composer require adldap2/adldap2
+```
+
+Use Adldap2:
+
+```php
+// Construct new Adldap instance.
+$ad = new \Adldap\Adldap();
+
+// Create a configuration array.
+$config = [
+ // An array of your LDAP hosts. You can use either
+ // the host name or the IP address of your host.
+ 'hosts' => ['ACME-DC01.corp.acme.org', '192.168.1.1'],
+
+ // The base distinguished name of your domain to perform searches upon.
+ 'base_dn' => 'dc=corp,dc=acme,dc=org',
+
+ // The account to use for querying / modifying LDAP records. This
+ // does not need to be an admin account. This can also
+ // be a full distinguished name of the user account.
+ 'username' => 'admin@corp.acme.org',
+ 'password' => 'password',
+];
+
+// Add a connection provider to Adldap.
+$ad->addProvider($config);
+
+try {
+ // If a successful connection is made to your server, the provider will be returned.
+ $provider = $ad->connect();
+
+ // Performing a query.
+ $results = $provider->search()->where('cn', '=', 'John Doe')->get();
+
+ // Finding a record.
+ $user = $provider->search()->find('jdoe');
+
+ // Creating a new LDAP entry. You can pass in attributes into the make methods.
+ $user = $provider->make()->user([
+ 'cn' => 'John Doe',
+ 'title' => 'Accountant',
+ 'description' => 'User Account',
+ ]);
+
+ // Setting a model's attribute.
+ $user->cn = 'John Doe';
+
+ // Saving the changes to your LDAP server.
+ if ($user->save()) {
+ // User was saved!
+ }
+} catch (\Adldap\Auth\BindException $e) {
+
+ // There was an issue binding / connecting to the server.
+
+}
+```
+
+## Versioning
+
+Adldap2 is versioned under the [Semantic Versioning](http://semver.org/) guidelines as much as possible.
+
+Releases will be numbered with the following format:
+
+`<major>.<minor>.<patch>`
+
+And constructed with the following guidelines:
+
+* Breaking backward compatibility bumps the major and resets the minor and patch.
+* New additions without breaking backward compatibility bumps the minor and resets the patch.
+* Bug fixes and misc changes bumps the patch.
+
+Minor versions are not maintained individually, and you're encouraged to upgrade through to the next minor version.
+
+Major versions are maintained individually through separate branches.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/searching.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/searching.md
new file mode 100644
index 0000000..2837767
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/searching.md
@@ -0,0 +1,662 @@
+# Searching
+
+## Introduction
+
+Using the Adldap2 query builder makes building LDAP queries feel effortless.
+
+It allows you to generate LDAP filters using a fluent and
+convenient interface, similar to Eloquent in Laravel.
+
+> **Note:** The Adldap2 query builder escapes all fields & values
+> given to its `where()` methods. There is no need to clean or
+> escape strings before passing them into the query builder.
+
+## Creating a new Query
+
+To create a new search query, call the `search()` method on your connection provider instance:
+
+```php
+$search = $provider->search();
+```
+
+Or you can chain all your methods if you'd prefer:
+
+```php
+$results = $provider->search()->where('cn', '=', 'John Doe')->get();
+```
+
+## Selects
+
+> **Note:** Fields are case in-sensitive. For example, you can
+> insert `CN`, `cn` or `cN`, they will return the same result.
+
+#### Selecting attributes
+
+Selecting only the LDAP attributes you need will increase the speed of your queries.
+
+```php
+// Passing in an array of attributes
+$search->select(['cn', 'samaccountname', 'telephone', 'mail']);
+
+// Passing in each attribute as an argument
+$search->select('cn', 'samaccountname', 'telephone', 'mail');
+```
+
+## Executing Searches
+
+#### Finding a specific record
+
+If you're trying to find a single record, but not sure what the record might be, use the `find()` method:
+
+```php
+$record = $search->find('John Doe');
+
+if ($record) {
+ // Record was found!
+} else {
+ // Hmm, looks like we couldn't find anything...
+}
+```
+
+> **Note**: Using the `find()` method will search for LDAP records using ANR
+> (ambiguous name resolution) and return the first result.
+>
+> Since ActiveDirectory is the only LDAP distribution that supports ANR,
+> an equivalent query will be created for other LDAP distributions
+> that are not compatible.
+>
+> For a more fine-tuned search, use the `findBy()` method below.
+
+##### Finding a record (or failing)
+
+If you'd like to try and find a single record and throw an exception when it hasn't been
+found, use the `findOrFail()` method:
+
+```php
+try {
+
+ $record = $search->findOrFail('John Doe');
+
+} catch (Adldap\Models\ModelNotFoundException $e) {
+ // Record wasn't found!
+}
+```
+
+#### Finding a record by a specific attribute
+
+If you're looking for a single record with a specific attribute, use the `findBy()` method:
+
+```php
+// We're looking for a record with the 'samaccountname' of 'jdoe'.
+$record = $search->findBy('samaccountname', 'jdoe');
+```
+
+##### Finding a record by a specific attribute (or failing)
+
+If you'd like to try and find a single record by a specific attribute and throw
+an exception when it cannot be found, use the `findByOrFail()` method:
+
+```php
+try {
+
+ $record = $search->findByOrFail('samaccountname', 'jdoe');
+
+} catch (Adldap\Models\ModelNotFoundException $e) {
+ // Record wasn't found!
+}
+```
+
+#### Finding a record by its distinguished name
+
+If you're looking for a single record with a specific DN, use the `findByDn()` method:
+
+```php
+$record = $search->findByDn('cn=John Doe,dc=corp,dc=org');
+```
+
+###### Finding a record by its distinguished name (or failing)
+
+If you'd like to try and find a single record by a specific DN and throw
+an exception when it hasn't been found, use the `findByDnOrFail()` method:
+
+```php
+try {
+
+ $record = $search->findByDnOrFail('cn=John Doe,dc=corp,dc=org');
+
+} catch (Adldap\Models\ModelNotFoundException $e) {
+ // Record wasn't found!
+}
+```
+
+#### Retrieving results
+
+To get the results from a search, simply call the `get()` method:
+
+```php
+$results = $search->select(['cn', 'samaccountname'])->get();
+```
+
+> **Note**: Executed searches via the `get()` method will return them inside an
+> `Illuminate\Support\Collection` instance (a glorified array), with allows
+> you to utilize [some extremely handy methods](https://laravel.com/docs/collections).
+>
+> Executed searches via the `first()` method will return **a model instance only**.
+
+##### Retrieving the first record
+
+To retrieve the first record of a search, call the `first()` method:
+
+```php
+$record = $search->first();
+```
+
+> **Note**: If you are using `sortBy()`, calling `first()` will not take this into account. Sorts
+> are performed **after** retrieving query results. If you would like the first record of
+> a sorted result set, call `first()` on a `Collection` of returned models.
+
+###### Retrieving the first record (or failing)
+
+To retrieve the first record of a search or throw an exception when one isn't found, call the `firstOrFail()` method:
+
+```php
+try {
+
+ $record = $search->firstOrFail();
+
+} catch (Adldap\Models\ModelNotFoundException $e) {
+ // Record wasn't found!
+}
+```
+
+## Limit
+
+To limit the results records returned from your LDAP server and increase the
+speed of your queries, you can use the `limit()` method:
+
+```php
+// This will only return 5 records that contain the name of 'John':
+$records = $search->where('cn', 'contains', 'John')->limit(5)->get();
+```
+
+## Wheres
+
+To perform a where clause on the search object, use the `where()` function:
+
+```php
+$search->where('cn', '=', 'John Doe');
+```
+
+This query would look for a record with the common name of 'John Doe' and return the results.
+
+We can also perform a 'where equals' without including the operator:
+
+```php
+$search->whereEquals('cn', 'John Doe');
+```
+
+We can also supply an array of key - value pairs to quickly add multiple wheres:
+
+```php
+$wheres = [
+ 'cn' => 'John Doe',
+ 'samaccountname' => 'jdoe',
+];
+
+$search->where($wheres);
+```
+
+Or, if you require conditionals, you can quickly add multiple wheres with nested arrays:
+
+```php
+$search->where([
+ ['cn', '=', 'John Doe'],
+ ['manager', '!', 'Suzy Doe'],
+]);
+```
+
+#### Where Starts With
+
+We could also perform a search for all objects beginning with the common name of 'John' using the `starts_with` operator:
+
+```php
+$results = $provider->search()->where('cn', 'starts_with', 'John')->get();
+
+// Or use the method whereStartsWith($attribute, $value):
+
+$results = $provider->search()->whereStartsWith('cn', 'John')->get();
+```
+
+#### Where Ends With
+
+We can also search for all objects that end with the common name of `Doe` using the `ends_with` operator:
+
+```php
+$results = $provider->search()->where('cn', 'ends_with', 'Doe')->get();
+
+// Or use the method whereEndsWith($attribute, $value):
+
+$results = $provider->search()->whereEndsWith('cn', 'Doe')->get();
+```
+
+#### Where Between
+
+To search for records between two values, use the `whereBetween` method.
+
+For the example below, we'll retrieve all users who were created between two dates:
+
+```php
+$from = (new DateTime('October 1st 2016'))->format('YmdHis.0\Z');
+$to = (new DateTime('January 1st 2017'))->format('YmdHis.0\Z');
+
+$users = $provider->search()
+ ->users()
+ ->whereBetween('whencreated', [$from, $to])
+ ->get();
+```
+
+#### Where Contains
+
+We can also search for all objects with a common name that contains `John Doe` using the `contains` operator:
+
+```php
+$results = $provider->search()->where('cn', 'contains', 'John Doe')->get();
+
+// Or use the method whereContains($attribute, $value):
+
+$results = $provider->search()->whereContains('cn', 'John Doe')->get();
+```
+
+##### Where Not Contains
+
+You can use a 'where not contains' to perform the inverse of a 'where contains':
+
+```php
+$results = $provider->search()->where('cn', 'not_contains', 'John Doe')->get();
+
+// Or use the method whereNotContains($attribute, $value):
+
+$results = $provider->search()->whereNotContains('cn', 'John Doe');
+```
+
+#### Where Has
+
+Or we can retrieve all objects that have a common name attribute using the wildcard operator (`*`):
+
+```php
+$results = $provider->search()->where('cn', '*')->get();
+
+// Or use the method whereHas($field):
+
+$results = $provider->search()->whereHas('cn')->get();
+```
+
+This type of filter syntax allows you to clearly see what your searching for.
+
+##### Where Not Has
+
+You can use a 'where not has' to perform the inverse of a 'where has':
+
+```php
+$results = $provider->search->where('cn', '!*')->get();
+
+// Or use the method whereNotHas($field):
+
+$results = $provider->search()->whereNotHas($field)->get();
+```
+
+## Or Wheres
+
+To perform an `or where` clause on the search object, use the `orWhere()` method. However,
+please be aware this function performs differently than it would on a database.
+
+For example:
+
+```php
+$results = $search
+ ->where('cn', '=', 'John Doe')
+ ->orWhere('cn', '=', 'Suzy Doe')
+ ->get();
+```
+
+This query would return no results. Since we're already defining that the common name (`cn`) must equal `John Doe`, applying
+the `orWhere()` does not amount to 'Look for an object with the common name as "John Doe" OR "Suzy Doe"'. This query would
+actually amount to 'Look for an object with the common name that <b>equals</b> "John Doe" OR "Suzy Doe"
+
+To solve the above problem, we would use `orWhere()` for both fields. For example:
+
+```php
+$results = $search
+ ->orWhere('cn', '=', 'John Doe')
+ ->orWhere('cn', '=', 'Suzy Doe')
+ ->get();
+```
+
+Now, we'll retrieve both John and Suzy's LDAP records, because the common name can equal either.
+
+> **Note**: You can also use all `where` methods as an or where, for example:
+> `orWhereHas()`, `orWhereContains()`, `orWhereStartsWith()`, `orWhereEndsWith()`
+
+## Dynamic Wheres
+
+To perform a dynamic where, simply suffix a `where` with the field you're looking for.
+
+This feature was directly ported from Laravel's Eloquent.
+
+Here's an example:
+
+```php
+// This query:
+$result = $search->where('cn', '=', 'John Doe')->first();
+
+// Can be converted to:
+$result = $search->whereCn('John Doe')->first();
+```
+
+You can perform this on **any** attribute:
+
+```php
+$result = $search->whereTelephonenumber('555-555-5555')->first();
+```
+
+You can also chain them:
+
+```php
+$result = $search
+ ->whereTelephonenumber('555-555-5555')
+ ->whereGivenname('John Doe')
+ ->whereSn('Doe')
+ ->first();
+```
+
+You can even perform multiple dynamic wheres by separating your fields by an `And`:
+
+```php
+// This would perform a search for a user with the
+// first name of 'John' and last name of 'Doe'.
+$result = $search->whereGivennameAndSn('John', 'Doe')->first();
+```
+
+## Nested Filters
+
+By default, the Adldap2 query builder automatically wraps your queries in `and` / `or` filters for you.
+However, if any further complexity is required, nested filters allow you
+to construct any query fluently and easily.
+
+#### andFilter
+
+The `andFilter` method accepts a closure which allows you to construct a query inside of an `and` LDAP filter:
+
+```php
+$query = $provider->search()->newQuery();
+
+// Creates the filter: (&(givenname=John)(sn=Doe))
+$results = $query->andFilter(function (Adldap\Query\Builder $q) {
+
+ $q->where('givenname', '=', 'John')
+ ->where('sn', '=', 'Doe');
+
+})->get();
+```
+
+The above query would return records that contain the first name `John` **and** the last name `Doe`.
+
+#### orFilter
+
+The `orFilter` method accepts a closure which allows you to construct a query inside of an `or` LDAP filter:
+
+```php
+$query = $provider->search()->newQuery();
+
+
+// Creates the filter: (|(givenname=John)(sn=Doe))
+$results = $query->orFilter(function (Adldap\Query\Builder $q) {
+
+ $q->where('givenname', '=', 'John')
+ ->where('sn', '=', 'Doe');
+
+})->get();
+```
+
+The above query would return records that contain the first name `John` **or** the last name `Doe`.
+
+#### notFilter
+
+The `notFilter` method accepts a closure which allows you to construct a query inside a `not` LDAP filter:
+
+```php
+$query = $provider->search()->newQuery();
+
+// Creates the filter: (!(givenname=John)(sn=Doe))
+$results = $query->notFilter(function (Adldap\Query\Builder $q) {
+
+ $q->where('givenname', '=', 'John')
+ ->where('sn', '=', 'Doe');
+
+})->get();
+```
+
+The above query would return records that **do not** contain the first name `John` **or** the last name `Doe`.
+
+#### Complex Nesting
+
+The above methods `andFilter` / `orFilter` can be chained together and nested
+as many times as you'd like for larger complex queries:
+
+```php
+$query = $provider->search()->newQuery();
+
+$query = $query->orFilter(function (Adldap\Query\Builder $q) {
+ $q->where('givenname', '=', 'John')->where('sn', '=', 'Doe');
+})->andFilter(function (Adldap\Query\Builder $q) {
+ $q->where('department', '=', 'Accounting')->where('title', '=', 'Manager');
+})->getUnescapedQuery();
+
+echo $query; // Returns '(&(|(givenname=John)(sn=Doe))(&(department=Accounting)(title=Manager)))'
+```
+
+## Raw Filters
+
+> **Note**: Raw filters are not escaped. **Do not** accept user input into the raw filter method.
+
+Sometimes you might just want to add a raw filter without using the query builder.
+You can do so by using the `rawFilter()` method:
+
+```php
+$filter = '(samaccountname=jdoe)';
+
+$results = $search->rawFilter($filter)->get();
+
+// Or use an array
+$filters = [
+ '(samaccountname=jdoe)',
+ '(surname=Doe)',
+];
+
+$results = $search->rawFilter($filters)->get();
+
+// Or use multiple arguments
+$results = $search->rawFilter($filters[0], $filters[1])->get();
+
+// Multiple raw filters will be automatically wrapped into an `and` filter:
+$query = $search->getUnescapedQuery();
+
+echo $query; // Returns (&(samaccountname=jdoe)(surname=Doe))
+```
+
+## Sorting
+
+Sorting is really useful when your displaying tabular LDAP results. You can
+easily perform sorts on any LDAP attribute by using the `sortBy()` method:
+
+```php
+$results = $search->whereHas('cn')->sortBy('cn', 'asc')->get();
+```
+
+You can also sort paginated results:
+
+```php
+$results = $search->whereHas('cn')->sortBy('cn', 'asc')->paginate(25);
+```
+
+> **Note**: Sorting occurs *after* results are returned. This is due
+> to PHP not having the functionality of sorting records on
+> the server side before they are returned.
+
+## Paginating
+
+Paginating your search results will allow you to return more results than
+your LDAP cap (usually 1000) and display your results in pages.
+
+> **Note**: Calling `paginate()` will retrieve **all** records from your LDAP server for the current query.
+>
+> This **does not** operate the same way pagination occurs in a database. Pagination of
+> an LDAP query simply allows you to return a larger result set than your
+> LDAP servers configured maximum (usually 1000).
+>
+> The pagination object is simply a collection that allows you to iterate
+> through all the resulting records easily and intuitively.
+
+To perform this, call the `paginate()` method instead of the `get()` method:
+
+```php
+$recordsPerPage = 50;
+
+$currentPage = $_GET['page'];
+
+// This would retrieve all records from your LDAP server inside a new Adldap\Objects\Paginator instance.
+$paginator = $search->paginate($recordsPerPage, $currentPage);
+
+// Returns total number of pages, int
+$paginator->getPages();
+
+// Returns current page number, int
+$paginator->getCurrentPage();
+
+// Returns the amount of entries allowed per page, int
+$paginator->getPerPage();
+
+// Returns all of the results in the entire paginated result
+$paginator->getResults();
+
+// Returns the total amount of retrieved entries, int
+$paginator->count();
+
+// Iterate over the results like normal
+foreach($paginator as $result)
+{
+ echo $result->getCommonName();
+}
+```
+
+## Scopes
+
+Search scopes allow you to easily retrieve common models of a particular 'scope'.
+
+Each scope simply applies the required filters to the search object
+that (when executed) will only return the relevant models.
+
+Here is a list of all available scopes:
+
+```php
+// Retrieve all users (Adldap\Models\User).
+$results = $search->users()->get();
+
+// Retrieve all printers (Adldap\Models\Printer).
+$results = $search->printers()->get();
+
+// Retrieve all organizational units (Adldap\Models\OrganizationalUnit).
+$results = $search->ous()->get();
+
+// Retrieve all organizational units (Adldap\Models\OrganizationalUnit).
+$results = $search->organizations()->get();
+
+// Retrieve all groups (Adldap\Models\Group).
+$results = $search->groups()->get();
+
+// Retrieve all containers (Adldap\Models\Container).
+$results = $search->containers()->get();
+
+// Retrieve all contacts (Adldap\Models\Contact).
+$results = $search->contacts()->get();
+
+// Retrieve all computers (Adldap\Models\Computer).
+$results = $search->computers()->get();
+```
+
+## Base DN
+
+To set the base DN of your search you can use one of two methods:
+
+```php
+// Using the `in()` method:
+$results = $provider->search()->in('ou=Accounting,dc=acme,dc=org')->get();
+
+// Using the `setDn()` method:
+$results = $provider->search()->setDn('ou=Accounting,dc=acme,dc=org')->get();
+
+// You can also include `in()` with the scope
+$results = $provider->search()->organizations()->in('ou=Accounting,dc=acme,dc=org')->get()
+
+```
+
+Either option will return the same results. Use which ever method you prefer to be more readable.
+
+## Search Options
+
+#### Recursive
+
+By default, all searches performed are recursive.
+
+If you'd like to disable recursive search and perform a single level search, use the `listing()` method:
+
+```php
+$result = $provider->search()->listing()->get();
+```
+
+This would perform an `ldap_listing()` instead of an `ldap_search()`.
+
+#### Read
+
+If you'd like to perform a read instead of a listing or a recursive search, use the `read()` method:
+
+```php
+$result = $provider->search()->read()->where('objectClass', '*')->get();
+```
+
+This would perform an `ldap_read()` instead of an `ldap_listing()` or an `ldap_search()`.
+
+> **Note**: Performing a `read()` will always return *one* record in your result.
+
+#### Raw
+
+If you'd like to retrieve the raw LDAP results, use the `raw()` method:
+
+```php
+$rawResults = $provider->search()->raw()->where('cn', '=', 'John Doe')->get();
+
+var_dump($rawResults); // Returns an array
+```
+
+## Retrieving the ran query
+
+If you'd like to retrieve the current query to save or run it at another
+time, use the `getQuery()` method on the query builder.
+
+This will return the escaped filter.
+
+```php
+$query = $provider->search()->where('cn', '=', 'John Doe')->getQuery();
+
+echo $query; // Returns '(cn=\4a\6f\68\6e\20\44\6f\65)'
+```
+
+To retrieve the unescaped filter, call the `getUnescapedQuery()` method:
+
+```php
+$query = $provider->search()->where('cn', '=', 'John Doe')->getUnescapedQuery();
+
+echo $query; // Returns '(cn=John Doe)'
+```
+
+Now that you know how to search your directory, lets move onto [creating / modifying LDAP records](models/model.md).
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/setup.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/setup.md
new file mode 100644
index 0000000..312165c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/setup.md
@@ -0,0 +1,552 @@
+# Setup
+
+## Configuration
+
+To configure your LDAP connections, you can use two methods:
+
+1. Using an array
+2. Using a `Adldap\Configuration\DomainConfiguration` object
+
+Either or will produce the same results. Use whichever you feel most comfortable with.
+
+### Using an array
+
+```php
+$config = [
+ 'hosts' => [
+ 'DC-01.corp.acme.org',
+ ],
+ '...'
+];
+```
+
+### Using a `DomainConfiguration` object
+
+```php
+// Setting options via first argument:
+$config = new Adldap\Configuration\DomainConfiguration([
+ 'hosts' => [
+ 'DC-01.corp.acme.org',
+ ],
+]);
+
+// Setting via the `set()` method:
+$config->set('hosts', [
+ 'DC-01.corp.acme.org',
+]);
+```
+
+### Options
+
+#### Array Example With All Options
+
+```php
+// Create the configuration array.
+$config = [
+ // Mandatory Configuration Options
+ 'hosts' => ['corp-dc1.corp.acme.org', 'corp-dc2.corp.acme.org'],
+ 'base_dn' => 'dc=corp,dc=acme,dc=org',
+ 'username' => 'admin',
+ 'password' => 'password',
+
+ // Optional Configuration Options
+ 'schema' => Adldap\Schemas\ActiveDirectory::class,
+ 'account_prefix' => 'ACME-',
+ 'account_suffix' => '@acme.org',
+ 'port' => 389,
+ 'follow_referrals' => false,
+ 'use_ssl' => false,
+ 'use_tls' => false,
+ 'version' => 3,
+ 'timeout' => 5,
+
+ // Custom LDAP Options
+ 'custom_options' => [
+ // See: http://php.net/ldap_set_option
+ LDAP_OPT_X_TLS_REQUIRE_CERT => LDAP_OPT_X_TLS_HARD
+ ]
+];
+```
+
+#### Required Options
+
+##### Hosts
+
+The hosts option is an array of IP addresses or hostnames located
+on your network that serve Active Directory.
+
+You insert as many servers or as little as you'd like depending on your forest (with the minimum of one of course).
+
+> **Note:** Do not append your port to your IP addresses or hostnames. Use the `port` configuration option instead.
+
+##### Base Distinguished Name
+
+The base distinguished name is the base distinguished name you'd like to perform operations on.
+
+An example base DN would be `DC=corp,DC=acme,DC=org`.
+
+If one is not defined, you will not retrieve any search results.
+
+> **Note**: Your base DN is **case insensitive**. You do not need to worry about incorrect casing.
+
+##### Username & Password
+
+To connect to your LDAP server, a username and password is required to be able to query and run operations on your server(s).
+
+You can use any account that has these permissions.
+
+> **Note**: To run administration level operations, such as resetting passwords,
+> this account **must** have permissions to do so on your directory.
+
+#### Optional Options
+
+##### Schema
+
+The schema option allows you to configure which directory you're connecting to.
+
+This is a somewhat optional, however this **must** be changed if you're connecting
+to an alternate LDAP variant such as OpenLDAP or FreeIPA.
+
+Below are available schemas:
+
+- `Adldap\Schemas\ActiveDirectory`
+- `Adldap\Schemas\OpenLDAP`
+- `Adldap\Schemas\FreeIPA`
+
+By default, this option is set to the `Adldap\Schemas\ActiveDirectory` schema.
+
+##### Account Prefix
+
+The account prefix option is a string to *prepend* to all usernames that go through the `Guard::attempt()` method.
+
+This option is just for convenience.
+
+It is usually not needed (if utilizing the account suffix), however the functionality is
+in place if you would like to only allow certain users with the specified prefix
+to login, or add a domain so your users do not have to specify one.
+
+##### Account Suffix
+
+The account suffix option is a string to *append* to all usernames that go
+through the `Adldap\Auth\Guard::attempt()` method.
+
+This option is just for convenience.
+
+An example use case for this would be inserting your LDAP users `userPrincipalName` suffix so you don't need to append it manually.
+
+For example, with a `account_suffix` in your configuration set to `@corp.acme.org`:
+
+```php
+$username = 'jdoe';
+$password = 'password';
+
+// Here, an `ldap_bind()` will be called with a username of 'jdoe@corp.acme.org`
+$provider->auth()->attempt($username, $password);
+```
+
+##### Port
+
+The port option is used for authenticating and binding to your LDAP server.
+
+The default ports are already used for non SSL and SSL connections (389 and 636).
+
+Only insert a port if your LDAP server uses a unique port.
+
+##### Follow Referrals
+
+The follow referrals option is a boolean to tell active directory to follow a referral to another server on your network if the server queried knows the information your asking for exists, but does not yet contain a copy of it locally.
+
+This option is defaulted to false.
+
+Disable this option if you're experiencing search / connectivity issues.
+
+For more information, visit: https://technet.microsoft.com/en-us/library/cc978014.aspx
+
+##### SSL & TLS
+
+These Boolean options enable an SSL or TLS connection to your LDAP server.
+
+Only **one** can be set to `true`. You must chose either or.
+
+> **Note**: You **must** enable SSL or TLS to reset passwords in ActiveDirectory.
+
+These options are definitely recommended if you have the ability to connect to your server securely.
+
+> **Note**: TLS is recommended over SSL, as SSL is now labelled as a depreciated mechanism for securely running LDAP operations.
+
+##### Version
+
+The LDAP version to use for your connection.
+
+Must be an integer and can either be `2` or `3`.
+
+##### Timeout
+
+The timeout option allows you to configure the amount of seconds to wait until
+your application receives a response from your LDAP server.
+
+The default is 5 seconds.
+
+##### Custom Options
+
+Arbitrary options can be set for the connection to fine-tune TLS and connection behavior.
+
+Please note that `LDAP_OPT_PROTOCOL_VERSION`, `LDAP_OPT_NETWORK_TIMEOUT` and `LDAP_OPT_REFERRALS` will be ignored if set.
+
+These are set above with the `version`, `timeout` and `follow_referrals` keys respectively.
+
+Valid options are listed in the [PHP documentation for ldap_set_option](http://php.net/ldap_set_option).
+
+## Getting Started
+
+Each LDAP connection you have will be contained inside the `Adldap` instance as its own **connection provider**.
+
+There are a couple of ways you can easily add each of your LDAP connections. Let's walk through them:
+
+**Using a configuration array:**
+```php
+$config = ['...'];
+
+$ad = new Adldap\Adldap();
+
+$ad->addProvider($config);
+
+// You can also specify the name of the
+// connection as the second argument:
+$ad->addProvider($config, 'connection-one');
+```
+
+**Using a DomainConfiguration object:**
+```php
+$ad = new Adldap\Adldap();
+
+$config = new Adldap\Configuration\DomainConfiguration(['...']);
+
+$ad->addProvider($config, 'connection-one');
+```
+
+**Using the constructor:**
+
+> **Note**: When inserting your configuration into a new `Adldap` instance, you
+> need to set a key for each connection. **This will be its connection name**.
+
+```php
+$connections = [
+ 'connection1' => [
+ 'hosts' => ['...'],
+ ],
+ 'connection2' => [
+ 'hosts' => ['...'],
+ ],
+];
+
+$ad = new Adldap\Adldap($connections);
+```
+
+## Connecting
+
+The easiest way to get connected is to call the `connect($name)` method on your `Adldap` instance.
+
+Its first argument accepts the name of your configured connection.
+
+This method will return you a connected **connection provider** when
+successful, and throw an exception when unsuccessful:
+
+```php
+$ad = new Adldap\Adldap();
+
+$config = ['...'];
+
+$connectionName = 'my-connection';
+
+$ad->addProvider($config, $connectionName);
+
+try {
+ $provider = $ad->connect($connectionName);
+
+ // Great, we're connected!
+} catch (Adldap\Auth\BindException $e) {
+ // Failed to connect.
+}
+```
+
+### Using an alternate username / password
+
+If you'd like to connect to your configured connection using a different username and password than your configuration, then simply provide them in the second and third arguments:
+
+```php
+$username = 'server-admin';
+$password = 'my-super-secret-password';
+
+$provider = $ad->connect($connectionName, $username, $password);
+```
+
+### Dynamically Connecting
+
+If you're like me and like chainable (fluent) API's in PHP, then dynamically connecting is a nice option to have.
+
+To dynamically connect, simply call any connection provider method on your `Adldap` instance.
+
+> **Note**: Your default connection will be used when dynamically connecting.
+> More on this below.
+
+Here's an example:
+
+```php
+$ad = new Adldap\Adldap();
+
+$ad->addProvider($config = ['...']);
+
+try {
+ $users = $ad->search()->users()->get();
+} catch (Adldap\Auth\BindException $e) {
+ // Failed to connect.
+}
+```
+
+### Anonymously Binding
+
+If you'd like to anonymously bind, set your `username` and `password` configuration to `null`:
+
+```php
+$ad = new Adldap\Adldap();
+
+$config = [
+ 'username' => null,
+ 'password' => null,
+];
+
+$ad->addProvider($config);
+
+try {
+ $provider = $ad->connect();
+
+ // ...
+} catch (BindException $e) {
+ // Failed.
+}
+```
+
+Or, manually bind your provider and don't pass in a `username` or `password` parameter:
+
+```php
+$config = [
+ 'hosts' => ['...'],
+];
+
+$ad->addProvider($config);
+
+$provider = $ad->getDefaultProvider();
+
+try {
+ $provider->auth()->bind();
+
+ // Successfully bound.
+} catch (BindException $e) {
+ // Failed.
+}
+```
+
+### Setting a Default Connection
+
+Setting a default LDAP connection is used for dynamically connecting.
+
+To set your default connection, call the `setDefaultProvider($name)` method:
+
+```php
+$ad->setDefaultProvider('my-connection');
+
+$computers = $ad->search()->computers()->get();
+```
+
+## Authenticating
+
+If you're looking to authenticate (bind) users using your LDAP connection, call
+the `auth()->attempt()` method on your provider instance:
+
+```php
+$username = 'jdoe';
+$password = 'Password@1';
+
+try {
+ if ($provider->auth()->attempt($username, $password)) {
+ // Passed.
+ } else {
+ // Failed.
+ }
+} catch (Adldap\Auth\UsernameRequiredException $e) {
+ // The user didn't supply a username.
+} catch (Adldap\Auth\PasswordRequiredException $e) {
+ // The user didn't supply a password.
+}
+```
+
+If you'd like all LDAP operations during the same request to be ran under the
+authenticated user, pass in `true` into the last paramter:
+
+```php
+if ($provider->auth()->attempt($username, $password, $bindAsUser = true)) {
+ // Passed.
+} else {
+ // Failed.
+}
+```
+
+---
+
+Now that you've learned the basics of configuration and
+getting yourself connected, continue on to learn
+[how to search your LDAP directory](searching.md).
+
+## Using Other LDAP Servers (OpenLDAP / FreeIPA / etc.)
+
+Alternate LDAP server variants such as OpenLDAP or FreeIPA contain
+some different attribute names than ActiveDirectory.
+
+The Adldap2 schema offers an attribute map for each available LDAP attribute, and
+is completely configurable and customizable.
+
+If you're using an alternate LDAP server variant such as OpenLDAP or FreeIPA, you **must** change the default schema inside your configuration array. If you do not, you won't receive the correct model instances for results, and you won't be
+able to utilize some standard methods available on these models.
+
+By default, Adldap2 is configured to be used with **Microsoft ActiveDirectory**.
+
+When creating your configuration array, set your schema using the `schema` key:
+
+
+**Using configuration array:**
+```php
+$ad = new Adldap\Adldap();
+
+$config = [
+ '...',
+ 'schema' => Adldap\Schemas\OpenLDAP::class
+];
+
+$ad->addProvider($config);
+```
+
+**Using configuration object:**
+```php
+$ad = new Adldap\Adldap();
+
+$config = new Adldap\Configuration\DomainConfiguration();
+
+$config->set('schema', Adldap\Schemas\OpenLDAP::class);
+
+$ad->addProvider($config);
+```
+
+Once you've set the schema of your connection provider, you can use the same API interacting with different LDAP servers.
+
+Continue onto the [searching](searching.md) documentation to learn how to begin querying your LDAP server(s).
+
+## Using G-Suite Secure LDAP Service
+
+G-Suite LDAP service only uses client certificates and no username + password, make sure yo match base_dn with your domian.
+
+```php
+$ad = new \Adldap\Adldap();
+
+// Create a configuration array.
+$config = [
+ 'hosts' => ['ldap.google.com'],
+ 'base_dn' => 'dc=your-domain,dc=com',
+ 'use_tls' => true,
+ 'version' => 3,
+ 'schema' => Adldap\Schemas\GSuite::class,
+ 'custom_options' => [
+ LDAP_OPT_X_TLS_CERTFILE => 'Google_2023_02_05_35779.crt',
+ LDAP_OPT_X_TLS_KEYFILE => 'Google_2023_02_05_35779.key',
+ ]
+];
+
+$ad->addProvider($config);
+
+try {
+ $provider = $ad->connect();
+
+ $results = $provider->search()->ous()->get();
+
+ echo 'OUs:'."\r\n";
+ echo '==============='."\r\n";
+ foreach($results as $ou) {
+ echo $ou->getDn()."\r\n";
+ }
+
+ echo "\r\n";
+
+ $results = $provider->search()->users()->get();
+
+ echo 'Users:'."\r\n";
+ echo '==============='."\r\n";
+ foreach($results as $user) {
+
+ echo $user->getAccountName()."\r\n";
+ }
+
+ echo "\r\n";
+
+ $results = $provider->search()->groups()->get();
+
+ echo 'Groups:'."\r\n";
+ echo '==============='."\r\n";
+ foreach($results as $group) {
+ echo $group->getCommonName().' | '.$group->getDisplayName()."\r\n";
+ }
+
+} catch (\Adldap\Auth\BindException $e) {
+
+ echo 'Error: '.$e->getMessage()."\r\n";
+}
+```
+
+## Raw Operations
+
+### Introduction
+
+If you want to connect to your LDAP server without utilizing Adldap's models (old fashion way), and want to get back the data in a raw format you can easily do so.
+
+If you call `getConnection()` on your connected provider instance, you can perform all LDAP functions on a container class that encapsulates all of PHP's LDAP methods.
+
+You can view all methods avaialble by browsing the LDAP class [here](https://github.com/Adldap2/Adldap2/blob/master/src/Connections/Ldap.php).
+
+Now for some examples:
+
+### Examples
+
+```php
+$ad = new Adldap\Adldap();
+
+$config = ['...'];
+
+$ad->addProvider($config);
+
+$provider = $ad->connect();
+
+$rawConnection = $provider->getConnection();
+
+// Performing a raw search.
+$result = $rawConnection->search($basedn = 'dc=corp,dc=acme,dc=org', $filter = "cn=johndoe", $selectedAttributes = ['cn', 'department']);
+
+$dn = "cn=John Smith,ou=Wizards,dc=example,dc=com";
+
+// Adding a new LDAP record.
+$result = $rawConnection->add($dn, $entry);
+
+// Batch modifying an LDAP record.
+$modifs = [
+ [
+ "attrib" => "telephoneNumber",
+ "modtype" => LDAP_MODIFY_BATCH_ADD,
+ "values" => ["+1 555 555 1717"],
+ ],
+];
+
+$result = $rawConnection->modifyBatch($dn, $modifs);
+
+// Deleting an LDAP record.
+$result = $rawConnection->delete($dn);
+
+// .. etc
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/troubleshooting.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/troubleshooting.md
new file mode 100644
index 0000000..c1e9f2a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/docs/troubleshooting.md
@@ -0,0 +1,122 @@
+# Troubleshooting
+
+#### Creating and Setting a Users Password
+
+To set a users password when you've created a new one, you need to enable their account, **then** set their password.
+
+For example:
+
+```php
+// Construct a new user instance.
+$user = $provider->make()->user();
+
+// Set the user profile details.
+$user->setAccountName('jdoe');
+$user->setFirstName('John');
+$user->setLastName('Doe');
+$user->setCompany('ACME');
+$user->setEmail('jdoe@acme.com');
+
+// Save the new user.
+if ($user->save()) {
+ // Enable the new user (using user account control).
+ $user->setUserAccountControl(512);
+
+ // Set new user password
+ $user->setPassword('Password123');
+
+ // Save the user.
+ if($user->save()) {
+ // The password was saved successfully.
+ }
+}
+```
+
+#### Determining and Troubleshooting a Binding Failure
+
+> **Note**: The below guide is using ActiveDirectory. Your mileage will vary using other LDAP distributions.
+
+To determine the reason why a bind attempt failed, you can use the event dispatcher to listen for
+the `Failed` event, and retrieve the errors that were returned from your LDAP server:
+
+```php
+use Adldap\Adldap;
+use Adldap\Auth\Events\Failed;
+
+$d = Adldap::getEventDispatcher();
+
+$d->listen(Failed::class, function (Failed $event) {
+ $conn = $event->connection;
+
+ echo $conn->getLastError(); // 'Invalid credentials'
+ echo $conn->getDiagnosticMessage(); // '80090308: LdapErr: DSID-0C09042A, comment: AcceptSecurityContext error, data 532, v3839'
+
+ if ($error = $conn->getDetailedError()) {
+ $error->getErrorCode(); // 49
+ $error->getErrorMessage(); // 'Invalid credentials'
+ $error->getDiagnosticMessage(); // '80090308: LdapErr: DSID-0C09042A, comment: AcceptSecurityContext error, data 532, v3839'
+ }
+});
+```
+
+The above diagnostic message can be parsed down further if needed. The error code after the 'data' string
+in the above message indicates several things about the bind failure. Here is a list:
+
+- 525 - user not found
+- 52e - invalid credentials
+- 530 - not permitted to logon at this time
+- 531 - not permitted to logon at this workstation
+- 532 - password expired
+- 533 - account disabled
+- 701 - account expired
+- 773 - user must reset password
+- 775 - user account locked
+
+From the example above, you can see that the authenticating account has their password expired, due to "532" error code.
+
+#### Retrieving All Records Inside a Group
+
+To retrieve all records inside a particular group (including nested groups), use the `rawFilter()` method:
+
+```php
+// The `memberof:1.2.840.113556.1.4.1941:` string indicates
+// that we want all nested group records as well.
+$filter = '(memberof:1.2.840.113556.1.4.1941:=CN=MyGroup,DC=example,DC=com)';
+
+$users = $provider->search()->rawFilter($filter)->get();
+```
+
+#### I'm connected but not getting any search results!
+
+The first thing you need to ensure is your `base_dn` in your configuration.
+
+Your `base_dn` needs to identical to the base DN on your domain. Even one mistyped character will result in no search results.
+
+If you also include an `ou` in your base DN (ex. `ou=Accounting,dc=corp,dc=acme,dc=org`), you will only receive results inside the `Accounting` OU.
+
+Once you're connected to your LDAP server, retrieve the Root DSE record.
+
+Here's a full example:
+
+```php
+$providers = [
+ 'default' => [
+ 'base_dn' => '',
+ '...',
+ ]
+];
+
+$ad = new Adldap\Adldap($providers);
+
+try {
+ $provider = $ad->connect();
+
+ $root = $provider->search()->getRootDse();
+
+ // ex. Returns 'dc=corp,dc=acme,dc=org'
+ die($root->getRootDomainNamingContext());
+
+} catch (Adldap\Auth\BindException $e) {
+ //
+}
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/license.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/license.md
new file mode 100644
index 0000000..c25dc60
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/license.md
@@ -0,0 +1,8 @@
+The MIT License (MIT)
+Copyright © Steve Bauman
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/phpunit.xml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/phpunit.xml
new file mode 100644
index 0000000..4f327fa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/phpunit.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="false"
+ backupStaticAttributes="false"
+ bootstrap="vendor/autoload.php"
+ colors="true"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ processIsolation="false"
+ stopOnFailure="false"
+ >
+ <testsuites>
+ <testsuite name="Adldap2 Test Suite">
+ <directory suffix="Test.php">./tests/</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist processUncoveredFilesFromWhitelist="true">
+ <directory suffix=".php">./src</directory>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/readme.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/readme.md
new file mode 100644
index 0000000..1311332
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/readme.md
@@ -0,0 +1,47 @@
+<p align="center">
+<strong>:wave: Hey there! Looking for something even easier to use for LDAP integration in your PHP applications?</strong>
+</br>
+<h3 align="center">
+ 🎉 Introducing <a href="https://github.com/DirectoryTree/LdapRecord" target="_blank" title="LdapRecord GitHub Repository">LdapRecord</a> 🎉
+</h3>
+</p>
+
+<p align="center">
+ <strong>
+ <a href="https://ldaprecord.com">LdapRecord</a> is the successor to Adldap2 - and comes with a ton of new features.
+ </strong> </br> Adldap2 will continue to be supported with bug fixes, <i>but will not receive new features.</i>
+</p>
+
+<p align="center">
+ <strong>
+ <a href="https://stevebauman.ca/why-ldap-record/">Read Why</a>
+ </strong>
+</p>
+
+<hr/>
+
+<h1 align="center">Adldap2</h1>
+
+<p align="center">
+ <a href="https://travis-ci.org/Adldap2/Adldap2"><img src="https://img.shields.io/travis/Adldap2/Adldap2.svg?style=flat-square"/></a>
+ <a href="https://scrutinizer-ci.com/g/Adldap2/Adldap2/?branch=master"><img src="https://img.shields.io/scrutinizer/g/adLDAP2/adLDAP2/master.svg?style=flat-square"/></a>
+ <a href="https://packagist.org/packages/adldap2/adldap2"><img src="https://img.shields.io/packagist/dt/adldap2/adldap2.svg?style=flat-square"/></a>
+ <a href="https://packagist.org/packages/adldap2/adldap2"><img src="https://img.shields.io/packagist/v/adldap2/adldap2.svg?style=flat-square"/></a>
+ <a href="https://packagist.org/packages/adldap2/adldap2"><img src="https://img.shields.io/packagist/l/adldap2/adldap2.svg?style=flat-square"/></a>
+</p>
+
+<p align="center">
+ Adldap2 is a PHP package that provides LDAP authentication and directory management tools using the <a href="https://en.wikipedia.org/wiki/Active_record_pattern">Active Record pattern</a>.
+</p>
+
+<h4 align="center">
+ <a href="http://adldap2.github.io/Adldap2/#/?id=quick-start">Quickstart</a>
+ <span> · </span>
+ <a href="http://adldap2.github.io/Adldap2/">Documentation</a>
+</h4>
+
+- **Up and running in minutes.** Effortlessly connect to your LDAP servers and start running queries & operations in a matter of minutes.
+
+- **Fluent query builder.** Building LDAP queries has never been so easy. Find the records you're looking for in a couple lines or less with a fluent interface.
+
+- **Supercharged Active Record.** Create and modify LDAP records with ease. All LDAP records are individual models. Simply modify the attributes on the model and save it to persist the changes to your LDAP server.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Adldap.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Adldap.php
new file mode 100644
index 0000000..5e60697
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Adldap.php
@@ -0,0 +1,194 @@
+<?php
+
+namespace Adldap;
+
+use Adldap\Log\EventLogger;
+use Adldap\Connections\Ldap;
+use InvalidArgumentException;
+use Adldap\Log\LogsInformation;
+use Adldap\Connections\Provider;
+use Adldap\Events\DispatchesEvents;
+use Adldap\Connections\ProviderInterface;
+use Adldap\Connections\ConnectionInterface;
+use Adldap\Configuration\DomainConfiguration;
+
+class Adldap implements AdldapInterface
+{
+ use DispatchesEvents;
+ use LogsInformation;
+ /**
+ * The default provider name.
+ *
+ * @var string
+ */
+ protected $default = 'default';
+
+ /**
+ * The connection providers.
+ *
+ * @var array
+ */
+ protected $providers = [];
+
+ /**
+ * The events to register listeners for during initialization.
+ *
+ * @var array
+ */
+ protected $listen = [
+ 'Adldap\Auth\Events\*',
+ 'Adldap\Query\Events\*',
+ 'Adldap\Models\Events\*',
+ ];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct(array $providers = [])
+ {
+ foreach ($providers as $name => $config) {
+ $this->addProvider($config, $name);
+ }
+
+ if ($default = key($providers)) {
+ $this->setDefaultProvider($default);
+ }
+
+ $this->initEventLogger();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addProvider($config, $name = 'default', ConnectionInterface $connection = null)
+ {
+ if ($this->isValidConfig($config)) {
+ $config = new Provider($config, $connection ?? new Ldap($name));
+ }
+
+ if ($config instanceof ProviderInterface) {
+ $this->providers[$name] = $config;
+
+ return $this;
+ }
+
+ throw new InvalidArgumentException(
+ "You must provide a configuration array or an instance of Adldap\Connections\ProviderInterface."
+ );
+ }
+
+ /**
+ * Determines if the given config is valid.
+ *
+ * @param mixed $config
+ *
+ * @return bool
+ */
+ protected function isValidConfig($config)
+ {
+ return is_array($config) || $config instanceof DomainConfiguration;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getProviders()
+ {
+ return $this->providers;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getProvider($name)
+ {
+ if (array_key_exists($name, $this->providers)) {
+ return $this->providers[$name];
+ }
+
+ throw new AdldapException("The connection provider '$name' does not exist.");
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setDefaultProvider($name = 'default')
+ {
+ if ($this->getProvider($name) instanceof ProviderInterface) {
+ $this->default = $name;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDefaultProvider()
+ {
+ return $this->getProvider($this->default);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function removeProvider($name)
+ {
+ unset($this->providers[$name]);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function connect($name = null, $username = null, $password = null)
+ {
+ $provider = $name ? $this->getProvider($name) : $this->getDefaultProvider();
+
+ return $provider->connect($username, $password);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __call($method, $parameters)
+ {
+ $provider = $this->getDefaultProvider();
+
+ if (! $provider->getConnection()->isBound()) {
+ $provider->connect();
+ }
+
+ return call_user_func_array([$provider, $method], $parameters);
+ }
+
+ /**
+ * Initializes the event logger.
+ *
+ * @return void
+ */
+ public function initEventLogger()
+ {
+ $dispatcher = static::getEventDispatcher();
+
+ $logger = $this->newEventLogger();
+
+ // We will go through each of our event wildcards and register their listener.
+ foreach ($this->listen as $event) {
+ $dispatcher->listen($event, function ($eventName, $events) use ($logger) {
+ foreach ($events as $event) {
+ $logger->log($event);
+ }
+ });
+ }
+ }
+
+ /**
+ * Returns a new event logger instance.
+ *
+ * @return EventLogger
+ */
+ protected function newEventLogger()
+ {
+ return new EventLogger(static::getLogger());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/AdldapException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/AdldapException.php
new file mode 100644
index 0000000..0939cac
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/AdldapException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap;
+
+class AdldapException extends \Exception
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/AdldapInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/AdldapInterface.php
new file mode 100644
index 0000000..9e1818f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/AdldapInterface.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace Adldap;
+
+use Adldap\Connections\ProviderInterface;
+use Adldap\Connections\ConnectionInterface;
+
+interface AdldapInterface
+{
+ /**
+ * Add a provider by the specified name.
+ *
+ * @param mixed $configuration
+ * @param string $name
+ * @param ConnectionInterface $connection
+ *
+ * @throws \InvalidArgumentException When an invalid type is given as the configuration argument.
+ *
+ * @return $this
+ */
+ public function addProvider($configuration, $name, ConnectionInterface $connection = null);
+
+ /**
+ * Returns all of the connection providers.
+ *
+ * @return array
+ */
+ public function getProviders();
+
+ /**
+ * Retrieves a Provider using its specified name.
+ *
+ * @param string $name
+ *
+ * @throws AdldapException When the specified provider does not exist.
+ *
+ * @return ProviderInterface
+ */
+ public function getProvider($name);
+
+ /**
+ * Sets the default provider.
+ *
+ * @param string $name
+ *
+ * @throws AdldapException When the specified provider does not exist.
+ */
+ public function setDefaultProvider($name);
+
+ /**
+ * Retrieves the first default provider.
+ *
+ * @throws AdldapException When no default provider exists.
+ *
+ * @return ProviderInterface
+ */
+ public function getDefaultProvider();
+
+ /**
+ * Removes a provider by the specified name.
+ *
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function removeProvider($name);
+
+ /**
+ * Connects to the specified provider.
+ *
+ * If no username and password is given, then the providers
+ * configured admin credentials are used.
+ *
+ * @param string|null $name
+ * @param string|null $username
+ * @param string|null $password
+ *
+ * @return ProviderInterface
+ */
+ public function connect($name = null, $username = null, $password = null);
+
+ /**
+ * Call methods upon the default provider dynamically.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/BindException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/BindException.php
new file mode 100644
index 0000000..aeef08b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/BindException.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Adldap\Auth;
+
+use Adldap\AdldapException;
+use Adldap\Connections\DetailedError;
+
+/**
+ * Class BindException.
+ *
+ * Thrown when binding to an LDAP connection fails.
+ */
+class BindException extends AdldapException
+{
+ /**
+ * The detailed LDAP error.
+ *
+ * @var DetailedError
+ */
+ protected $detailedError;
+
+ /**
+ * Sets the detailed error.
+ *
+ * @param DetailedError|null $error
+ *
+ * @return $this
+ */
+ public function setDetailedError(DetailedError $error = null)
+ {
+ $this->detailedError = $error;
+
+ return $this;
+ }
+
+ /**
+ * Returns the detailed error.
+ *
+ * @return DetailedError|null
+ */
+ public function getDetailedError()
+ {
+ return $this->detailedError;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Attempting.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Attempting.php
new file mode 100644
index 0000000..06eb839
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Attempting.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Auth\Events;
+
+class Attempting extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Binding.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Binding.php
new file mode 100644
index 0000000..aa52b4b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Binding.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Auth\Events;
+
+class Binding extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Bound.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Bound.php
new file mode 100644
index 0000000..5fc835d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Bound.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Auth\Events;
+
+class Bound extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Event.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Event.php
new file mode 100644
index 0000000..1dca6c7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Event.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace Adldap\Auth\Events;
+
+use Adldap\Connections\ConnectionInterface;
+
+abstract class Event
+{
+ /**
+ * The connection that the username and password is being bound on.
+ *
+ * @var ConnectionInterface
+ */
+ protected $connection;
+
+ /**
+ * The username that is being used for binding.
+ *
+ * @var string
+ */
+ protected $username;
+
+ /**
+ * The password that is being used for binding.
+ *
+ * @var string
+ */
+ protected $password;
+
+ /**
+ * Constructor.
+ *
+ * @param ConnectionInterface $connection
+ * @param string $username
+ * @param string $password
+ */
+ public function __construct(ConnectionInterface $connection, $username, $password)
+ {
+ $this->connection = $connection;
+ $this->username = $username;
+ $this->password = $password;
+ }
+
+ /**
+ * Returns the events connection.
+ *
+ * @return ConnectionInterface
+ */
+ public function getConnection()
+ {
+ return $this->connection;
+ }
+
+ /**
+ * Returns the authentication events username.
+ *
+ * @return string
+ */
+ public function getUsername()
+ {
+ return $this->username;
+ }
+
+ /**
+ * Returns the authentication events password.
+ *
+ * @return string
+ */
+ public function getPassword()
+ {
+ return $this->password;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Failed.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Failed.php
new file mode 100644
index 0000000..e96746e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Failed.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Auth\Events;
+
+class Failed extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Passed.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Passed.php
new file mode 100644
index 0000000..56ece18
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Events/Passed.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Auth\Events;
+
+class Passed extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Guard.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Guard.php
new file mode 100644
index 0000000..5a0ab4b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/Guard.php
@@ -0,0 +1,259 @@
+<?php
+
+namespace Adldap\Auth;
+
+use Exception;
+use Throwable;
+use Adldap\Auth\Events\Bound;
+use Adldap\Auth\Events\Failed;
+use Adldap\Auth\Events\Passed;
+use Adldap\Auth\Events\Binding;
+use Adldap\Auth\Events\Attempting;
+use Adldap\Events\DispatcherInterface;
+use Adldap\Connections\ConnectionInterface;
+use Adldap\Configuration\DomainConfiguration;
+
+/**
+ * Class Guard.
+ *
+ * Binds users to the current connection.
+ */
+class Guard implements GuardInterface
+{
+ /**
+ * The connection to bind to.
+ *
+ * @var ConnectionInterface
+ */
+ protected $connection;
+
+ /**
+ * The domain configuration to utilize.
+ *
+ * @var DomainConfiguration
+ */
+ protected $configuration;
+
+ /**
+ * The event dispatcher.
+ *
+ * @var DispatcherInterface
+ */
+ protected $events;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct(ConnectionInterface $connection, DomainConfiguration $configuration)
+ {
+ $this->connection = $connection;
+ $this->configuration = $configuration;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attempt($username, $password, $bindAsUser = false)
+ {
+ $this->validateCredentials($username, $password);
+
+ $this->fireAttemptingEvent($username, $password);
+
+ try {
+ $this->bind(
+ $this->applyPrefixAndSuffix($username),
+ $password
+ );
+
+ $result = true;
+
+ $this->firePassedEvent($username, $password);
+ } catch (BindException $e) {
+ // We'll catch the BindException here to allow
+ // developers to use a simple if / else
+ // using the attempt method.
+ $result = false;
+ }
+
+ // If we're not allowed to bind as the user,
+ // we'll rebind as administrator.
+ if ($bindAsUser === false) {
+ // We won't catch any BindException here so we can
+ // catch rebind failures. However this shouldn't
+ // occur if our credentials are correct
+ // in the first place.
+ $this->bindAsAdministrator();
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function bind($username = null, $password = null)
+ {
+ $this->fireBindingEvent($username, $password);
+
+ try {
+ if (@$this->connection->bind($username, $password) === true) {
+ $this->fireBoundEvent($username, $password);
+ } else {
+ throw new Exception($this->connection->getLastError(), $this->connection->errNo());
+ }
+ } catch (Throwable $e) {
+ $this->fireFailedEvent($username, $password);
+
+ throw (new BindException($e->getMessage(), $e->getCode(), $e))
+ ->setDetailedError($this->connection->getDetailedError());
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function bindAsAdministrator()
+ {
+ $this->bind(
+ $this->configuration->get('username'),
+ $this->configuration->get('password')
+ );
+ }
+
+ /**
+ * Get the event dispatcher instance.
+ *
+ * @return DispatcherInterface
+ */
+ public function getDispatcher()
+ {
+ return $this->events;
+ }
+
+ /**
+ * Sets the event dispatcher instance.
+ *
+ * @param DispatcherInterface $dispatcher
+ *
+ * @return void
+ */
+ public function setDispatcher(DispatcherInterface $dispatcher)
+ {
+ $this->events = $dispatcher;
+ }
+
+ /**
+ * Applies the prefix and suffix to the given username.
+ *
+ * @param string $username
+ *
+ * @throws \Adldap\Configuration\ConfigurationException If account_suffix or account_prefix do not
+ * exist in the providers domain configuration
+ *
+ * @return string
+ */
+ protected function applyPrefixAndSuffix($username)
+ {
+ $prefix = $this->configuration->get('account_prefix');
+ $suffix = $this->configuration->get('account_suffix');
+
+ return $prefix.$username.$suffix;
+ }
+
+ /**
+ * Validates the specified username and password from being empty.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @throws PasswordRequiredException When the given password is empty.
+ * @throws UsernameRequiredException When the given username is empty.
+ */
+ protected function validateCredentials($username, $password)
+ {
+ if (empty($username)) {
+ // Check for an empty username.
+ throw new UsernameRequiredException('A username must be specified.');
+ }
+
+ if (empty($password)) {
+ // Check for an empty password.
+ throw new PasswordRequiredException('A password must be specified.');
+ }
+ }
+
+ /**
+ * Fire the attempting event.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @return void
+ */
+ protected function fireAttemptingEvent($username, $password)
+ {
+ if (isset($this->events)) {
+ $this->events->fire(new Attempting($this->connection, $username, $password));
+ }
+ }
+
+ /**
+ * Fire the passed event.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @return void
+ */
+ protected function firePassedEvent($username, $password)
+ {
+ if (isset($this->events)) {
+ $this->events->fire(new Passed($this->connection, $username, $password));
+ }
+ }
+
+ /**
+ * Fire the failed event.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @return void
+ */
+ protected function fireFailedEvent($username, $password)
+ {
+ if (isset($this->events)) {
+ $this->events->fire(new Failed($this->connection, $username, $password));
+ }
+ }
+
+ /**
+ * Fire the binding event.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @return void
+ */
+ protected function fireBindingEvent($username, $password)
+ {
+ if (isset($this->events)) {
+ $this->events->fire(new Binding($this->connection, $username, $password));
+ }
+ }
+
+ /**
+ * Fire the bound event.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @return void
+ */
+ protected function fireBoundEvent($username, $password)
+ {
+ if (isset($this->events)) {
+ $this->events->fire(new Bound($this->connection, $username, $password));
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/GuardInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/GuardInterface.php
new file mode 100644
index 0000000..e10da37
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/GuardInterface.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Adldap\Auth;
+
+use Adldap\Connections\ConnectionInterface;
+use Adldap\Configuration\DomainConfiguration;
+
+interface GuardInterface
+{
+ /**
+ * Constructor.
+ *
+ * @param ConnectionInterface $connection
+ * @param DomainConfiguration $configuration
+ */
+ public function __construct(ConnectionInterface $connection, DomainConfiguration $configuration);
+
+ /**
+ * Authenticates a user using the specified credentials.
+ *
+ * @param string $username The users LDAP username.
+ * @param string $password The users LDAP password.
+ * @param bool $bindAsUser Whether or not to bind as the user.
+ *
+ * @throws \Adldap\Auth\BindException When re-binding to your LDAP server fails.
+ * @throws \Adldap\Auth\UsernameRequiredException When username is empty.
+ * @throws \Adldap\Auth\PasswordRequiredException When password is empty.
+ *
+ * @return bool
+ */
+ public function attempt($username, $password, $bindAsUser = false);
+
+ /**
+ * Binds to the current connection using the inserted credentials.
+ *
+ * @param string|null $username
+ * @param string|null $password
+ *
+ * @throws \Adldap\Auth\BindException If binding to the LDAP server fails.
+ * @throws \Adldap\Connections\ConnectionException If upgrading the connection to TLS fails
+ *
+ * @return void
+ */
+ public function bind($username = null, $password = null);
+
+ /**
+ * Binds to the current LDAP server using the
+ * configuration administrator credentials.
+ *
+ * @throws \Adldap\Auth\BindException When binding as your administrator account fails.
+ *
+ * @return void
+ */
+ public function bindAsAdministrator();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/PasswordRequiredException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/PasswordRequiredException.php
new file mode 100644
index 0000000..70a76b9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/PasswordRequiredException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Adldap\Auth;
+
+use Adldap\AdldapException;
+
+class PasswordRequiredException extends AdldapException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/UsernameRequiredException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/UsernameRequiredException.php
new file mode 100644
index 0000000..4b48724
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Auth/UsernameRequiredException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Adldap\Auth;
+
+use Adldap\AdldapException;
+
+class UsernameRequiredException extends AdldapException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/ConfigurationException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/ConfigurationException.php
new file mode 100644
index 0000000..af62ce4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/ConfigurationException.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace Adldap\Configuration;
+
+use Adldap\AdldapException;
+
+/**
+ * Class ConfigurationException.
+ *
+ * Thrown when a configuration value does not exist, or a
+ * configuration value being set is not valid.
+ */
+class ConfigurationException extends AdldapException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/DomainConfiguration.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/DomainConfiguration.php
new file mode 100644
index 0000000..f1e4fb6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/DomainConfiguration.php
@@ -0,0 +1,161 @@
+<?php
+
+namespace Adldap\Configuration;
+
+use Adldap\Schemas\ActiveDirectory;
+use Adldap\Connections\ConnectionInterface;
+
+/**
+ * Class DomainConfiguration.
+ *
+ * Contains an array of configuration options for a single LDAP connection.
+ */
+class DomainConfiguration
+{
+ /**
+ * The configuration options array.
+ *
+ * The default values for each key indicate the type of value it requires.
+ *
+ * @var array
+ */
+ protected $options = [
+ // An array of LDAP hosts.
+ 'hosts' => [],
+
+ // The global LDAP operation timeout limit in seconds.
+ 'timeout' => 5,
+
+ // The LDAP version to utilize.
+ 'version' => 3,
+
+ // The port to use for connecting to your hosts.
+ 'port' => ConnectionInterface::PORT,
+
+ // The schema to use for your LDAP connection.
+ 'schema' => ActiveDirectory::class,
+
+ // The base distinguished name of your domain.
+ 'base_dn' => '',
+
+ // The username to connect to your hosts with.
+ 'username' => '',
+
+ // The password that is utilized with the above user.
+ 'password' => '',
+
+ // The account prefix to use when authenticating users.
+ 'account_prefix' => null,
+
+ // The account suffix to use when authenticating users.
+ 'account_suffix' => null,
+
+ // Whether or not to use SSL when connecting to your hosts.
+ 'use_ssl' => false,
+
+ // Whether or not to use TLS when connecting to your hosts.
+ 'use_tls' => false,
+
+ // Whether or not follow referrals is enabled when performing LDAP operations.
+ 'follow_referrals' => false,
+
+ // Custom LDAP options that you'd like to utilize.
+ 'custom_options' => [],
+ ];
+
+ /**
+ * Constructor.
+ *
+ * @param array $options
+ *
+ * @throws ConfigurationException When an option value given is an invalid type.
+ */
+ public function __construct(array $options = [])
+ {
+ foreach ($options as $key => $value) {
+ $this->set($key, $value);
+ }
+ }
+
+ /**
+ * Sets a configuration option.
+ *
+ * Throws an exception if the specified option does
+ * not exist, or if it's an invalid type.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @throws ConfigurationException When an option value given is an invalid type.
+ */
+ public function set($key, $value)
+ {
+ if ($this->validate($key, $value)) {
+ $this->options[$key] = $value;
+ }
+ }
+
+ /**
+ * Returns the value for the specified configuration options.
+ *
+ * Throws an exception if the specified option does not exist.
+ *
+ * @param string $key
+ *
+ * @throws ConfigurationException When the option specified does not exist.
+ *
+ * @return mixed
+ */
+ public function get($key)
+ {
+ if ($this->has($key)) {
+ return $this->options[$key];
+ }
+
+ throw new ConfigurationException("Option {$key} does not exist.");
+ }
+
+ /**
+ * Checks if a configuration option exists.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function has($key)
+ {
+ return array_key_exists($key, $this->options);
+ }
+
+ /**
+ * Validates the new configuration option against its
+ * default value to ensure it's the correct type.
+ *
+ * If an invalid type is given, an exception is thrown.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @throws ConfigurationException When an option value given is an invalid type.
+ *
+ * @return bool
+ */
+ protected function validate($key, $value)
+ {
+ $default = $this->get($key);
+
+ if (is_array($default)) {
+ $validator = new Validators\ArrayValidator($key, $value);
+ } elseif (is_int($default)) {
+ $validator = new Validators\IntegerValidator($key, $value);
+ } elseif (is_bool($default)) {
+ $validator = new Validators\BooleanValidator($key, $value);
+ } elseif (class_exists($default)) {
+ $validator = new Validators\ClassValidator($key, $value);
+ } else {
+ $validator = new Validators\StringOrNullValidator($key, $value);
+ }
+
+ return $validator->validate();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/ArrayValidator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/ArrayValidator.php
new file mode 100644
index 0000000..ec5bdb0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/ArrayValidator.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Adldap\Configuration\Validators;
+
+use Adldap\Configuration\ConfigurationException;
+
+/**
+ * Class ArrayValidator.
+ *
+ * Validates that the configuration value is an array.
+ */
+class ArrayValidator extends Validator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate()
+ {
+ if (!is_array($this->value)) {
+ throw new ConfigurationException("Option {$this->key} must be an array.");
+ }
+
+ return true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/BooleanValidator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/BooleanValidator.php
new file mode 100644
index 0000000..23b4846
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/BooleanValidator.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Adldap\Configuration\Validators;
+
+use Adldap\Configuration\ConfigurationException;
+
+/**
+ * Class BooleanValidator.
+ *
+ * Validates that the configuration value is a boolean.
+ */
+class BooleanValidator extends Validator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate()
+ {
+ if (!is_bool($this->value)) {
+ throw new ConfigurationException("Option {$this->key} must be a boolean.");
+ }
+
+ return true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/ClassValidator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/ClassValidator.php
new file mode 100644
index 0000000..924c35f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/ClassValidator.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Adldap\Configuration\Validators;
+
+use Adldap\Configuration\ConfigurationException;
+
+class ClassValidator extends Validator
+{
+ /**
+ * Validates the configuration value.
+ *
+ * @throws ConfigurationException When the value given fails validation.
+ *
+ * @return bool
+ */
+ public function validate()
+ {
+ if (!class_exists($this->value)) {
+ throw new ConfigurationException("Option {$this->key} must be a valid class.");
+ }
+
+ return true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/IntegerValidator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/IntegerValidator.php
new file mode 100644
index 0000000..cd783c4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/IntegerValidator.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Adldap\Configuration\Validators;
+
+use Adldap\Configuration\ConfigurationException;
+
+/**
+ * Class IntegerValidator.
+ *
+ * Validates that the configuration value is an integer / number.
+ */
+class IntegerValidator extends Validator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate()
+ {
+ if (!is_numeric($this->value)) {
+ throw new ConfigurationException("Option {$this->key} must be an integer.");
+ }
+
+ return true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/StringOrNullValidator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/StringOrNullValidator.php
new file mode 100644
index 0000000..717c952
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/StringOrNullValidator.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Adldap\Configuration\Validators;
+
+use Adldap\Configuration\ConfigurationException;
+
+/**
+ * Class StringOrNullValidator.
+ *
+ * Validates that the configuration value is a string or null.
+ */
+class StringOrNullValidator extends Validator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function validate()
+ {
+ if (is_string($this->value) || is_null($this->value)) {
+ return true;
+ }
+
+ throw new ConfigurationException("Option {$this->key} must be a string or null.");
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/Validator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/Validator.php
new file mode 100644
index 0000000..983c98c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Configuration/Validators/Validator.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace Adldap\Configuration\Validators;
+
+/**
+ * Class Validator.
+ *
+ * Validates configuration values.
+ */
+abstract class Validator
+{
+ /**
+ * The configuration key under validation.
+ *
+ * @var string
+ */
+ protected $key;
+
+ /**
+ * The configuration value under validation.
+ *
+ * @var mixed
+ */
+ protected $value;
+
+ /**
+ * Constructor.
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ public function __construct($key, $value)
+ {
+ $this->key = $key;
+ $this->value = $value;
+ }
+
+ /**
+ * Validates the configuration value.
+ *
+ * @throws \Adldap\Configuration\ConfigurationException When the value given fails validation.
+ *
+ * @return bool
+ */
+ abstract public function validate();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/ConnectionException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/ConnectionException.php
new file mode 100644
index 0000000..d8004e6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/ConnectionException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Adldap\Connections;
+
+use Adldap\AdldapException;
+
+class ConnectionException extends AdldapException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/ConnectionInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/ConnectionInterface.php
new file mode 100644
index 0000000..39ddc0e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/ConnectionInterface.php
@@ -0,0 +1,539 @@
+<?php
+
+namespace Adldap\Connections;
+
+/**
+ * The Connection interface used for making connections. Implementing
+ * this interface on connection classes helps unit and functional
+ * test classes that require a connection.
+ *
+ * Interface ConnectionInterface
+ */
+interface ConnectionInterface
+{
+ /**
+ * The SSL LDAP protocol string.
+ *
+ * @var string
+ */
+ const PROTOCOL_SSL = 'ldaps://';
+
+ /**
+ * The standard LDAP protocol string.
+ *
+ * @var string
+ */
+ const PROTOCOL = 'ldap://';
+
+ /**
+ * The LDAP SSL port number.
+ *
+ * @var string
+ */
+ const PORT_SSL = 636;
+
+ /**
+ * The standard LDAP port number.
+ *
+ * @var string
+ */
+ const PORT = 389;
+
+ /**
+ * Constructor.
+ *
+ * @param string|null $name The connection name.
+ */
+ public function __construct($name = null);
+
+ /**
+ * Returns true / false if the current connection instance is using SSL.
+ *
+ * @return bool
+ */
+ public function isUsingSSL();
+
+ /**
+ * Returns true / false if the current connection instance is using TLS.
+ *
+ * @return bool
+ */
+ public function isUsingTLS();
+
+ /**
+ * Returns true / false if the current connection is able to modify passwords.
+ *
+ * @return bool
+ */
+ public function canChangePasswords();
+
+ /**
+ * Returns true / false if the current connection is bound.
+ *
+ * @return bool
+ */
+ public function isBound();
+
+ /**
+ * Sets the current connection to use SSL.
+ *
+ * @param bool $enabled
+ *
+ * @return ConnectionInterface
+ */
+ public function ssl($enabled = true);
+
+ /**
+ * Sets the current connection to use TLS.
+ *
+ * @param bool $enabled
+ *
+ * @return ConnectionInterface
+ */
+ public function tls($enabled = true);
+
+ /**
+ * Returns the full LDAP host URL.
+ *
+ * Ex: ldap://192.168.1.1:386
+ *
+ * @return string|null
+ */
+ public function getHost();
+
+ /**
+ * Returns the connections name.
+ *
+ * @return string|null
+ */
+ public function getName();
+
+ /**
+ * Get the current connection.
+ *
+ * @return mixed
+ */
+ public function getConnection();
+
+ /**
+ * Retrieve the entries from a search result.
+ *
+ * @link http://php.net/manual/en/function.ldap-get-entries.php
+ *
+ * @param $searchResult
+ *
+ * @return mixed
+ */
+ public function getEntries($searchResult);
+
+ /**
+ * Returns the number of entries from a search result.
+ *
+ * @link http://php.net/manual/en/function.ldap-count-entries.php
+ *
+ * @param $searchResult
+ *
+ * @return int
+ */
+ public function countEntries($searchResult);
+
+ /**
+ * Compare value of attribute found in entry specified with DN.
+ *
+ * @link http://php.net/manual/en/function.ldap-compare.php
+ *
+ * @param string $dn
+ * @param string $attribute
+ * @param string $value
+ *
+ * @return mixed
+ */
+ public function compare($dn, $attribute, $value);
+
+ /**
+ * Retrieves the first entry from a search result.
+ *
+ * @link http://php.net/manual/en/function.ldap-first-entry.php
+ *
+ * @param $searchResult
+ *
+ * @return mixed
+ */
+ public function getFirstEntry($searchResult);
+
+ /**
+ * Retrieves the next entry from a search result.
+ *
+ * @link http://php.net/manual/en/function.ldap-next-entry.php
+ *
+ * @param $entry
+ *
+ * @return mixed
+ */
+ public function getNextEntry($entry);
+
+ /**
+ * Retrieves the ldap entry's attributes.
+ *
+ * @link http://php.net/manual/en/function.ldap-get-attributes.php
+ *
+ * @param $entry
+ *
+ * @return mixed
+ */
+ public function getAttributes($entry);
+
+ /**
+ * Retrieve the last error on the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-error.php
+ *
+ * @return string
+ */
+ public function getLastError();
+
+ /**
+ * Return detailed information about an error.
+ *
+ * Returns false when there was a successful last request.
+ *
+ * Returns DetailedError when there was an error.
+ *
+ * @return DetailedError|null
+ */
+ public function getDetailedError();
+
+ /**
+ * Get all binary values from the specified result entry.
+ *
+ * @link http://php.net/manual/en/function.ldap-get-values-len.php
+ *
+ * @param $entry
+ * @param $attribute
+ *
+ * @return array
+ */
+ public function getValuesLen($entry, $attribute);
+
+ /**
+ * Sets an option on the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-set-option.php
+ *
+ * @param int $option
+ * @param mixed $value
+ *
+ * @return mixed
+ */
+ public function setOption($option, $value);
+
+ /**
+ * Sets options on the current connection.
+ *
+ * @param array $options
+ *
+ * @return mixed
+ */
+ public function setOptions(array $options = []);
+
+ /**
+ * Set a callback function to do re-binds on referral chasing.
+ *
+ * @link http://php.net/manual/en/function.ldap-set-rebind-proc.php
+ *
+ * @param callable $callback
+ *
+ * @return bool
+ */
+ public function setRebindCallback(callable $callback);
+
+ /**
+ * Connects to the specified hostname using the specified port.
+ *
+ * @link http://php.net/manual/en/function.ldap-start-tls.php
+ *
+ * @param string|array $hostname
+ * @param int $port
+ *
+ * @return mixed
+ */
+ public function connect($hostname = [], $port = 389);
+
+ /**
+ * Starts a connection using TLS.
+ *
+ * @link http://php.net/manual/en/function.ldap-start-tls.php
+ *
+ * @throws ConnectionException If starting TLS fails.
+ *
+ * @return mixed
+ */
+ public function startTLS();
+
+ /**
+ * Binds to the current connection using the specified username and password.
+ * If sasl is true, the current connection is bound using SASL.
+ *
+ * @link http://php.net/manual/en/function.ldap-bind.php
+ *
+ * @param string $username
+ * @param string $password
+ * @param bool $sasl
+ *
+ * @throws ConnectionException If starting TLS fails.
+ *
+ * @return bool
+ */
+ public function bind($username, $password, $sasl = false);
+
+ /**
+ * Closes the current connection.
+ *
+ * Returns false if no connection is present.
+ *
+ * @link http://php.net/manual/en/function.ldap-close.php
+ *
+ * @return bool
+ */
+ public function close();
+
+ /**
+ * Performs a search on the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-search.php
+ *
+ * @param string $dn
+ * @param string $filter
+ * @param array $fields
+ * @param bool $onlyAttributes
+ * @param int $size
+ * @param int $time
+ *
+ * @return mixed
+ */
+ public function search($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0);
+
+ /**
+ * Reads an entry on the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-read.php
+ *
+ * @param string $dn
+ * @param $filter
+ * @param array $fields
+ * @param bool $onlyAttributes
+ * @param int $size
+ * @param int $time
+ *
+ * @return mixed
+ */
+ public function read($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0);
+
+ /**
+ * Performs a single level search on the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-list.php
+ *
+ * @param string $dn
+ * @param string $filter
+ * @param array $attributes
+ * @param bool $onlyAttributes
+ * @param int $size
+ * @param int $time
+ *
+ * @return mixed
+ */
+ public function listing($dn, $filter, array $attributes, $onlyAttributes = false, $size = 0, $time = 0);
+
+ /**
+ * Adds an entry to the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-add.php
+ *
+ * @param string $dn
+ * @param array $entry
+ *
+ * @return bool
+ */
+ public function add($dn, array $entry);
+
+ /**
+ * Deletes an entry on the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-delete.php
+ *
+ * @param string $dn
+ *
+ * @return bool
+ */
+ public function delete($dn);
+
+ /**
+ * Modify the name of an entry on the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-rename.php
+ *
+ * @param string $dn
+ * @param string $newRdn
+ * @param string $newParent
+ * @param bool $deleteOldRdn
+ *
+ * @return bool
+ */
+ public function rename($dn, $newRdn, $newParent, $deleteOldRdn = false);
+
+ /**
+ * Modifies an existing entry on the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-modify.php
+ *
+ * @param string $dn
+ * @param array $entry
+ *
+ * @return bool
+ */
+ public function modify($dn, array $entry);
+
+ /**
+ * Batch modifies an existing entry on the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-modify-batch.php
+ *
+ * @param string $dn
+ * @param array $values
+ *
+ * @return mixed
+ */
+ public function modifyBatch($dn, array $values);
+
+ /**
+ * Add attribute values to current attributes.
+ *
+ * @link http://php.net/manual/en/function.ldap-mod-add.php
+ *
+ * @param string $dn
+ * @param array $entry
+ *
+ * @return mixed
+ */
+ public function modAdd($dn, array $entry);
+
+ /**
+ * Replaces attribute values with new ones.
+ *
+ * @link http://php.net/manual/en/function.ldap-mod-replace.php
+ *
+ * @param string $dn
+ * @param array $entry
+ *
+ * @return mixed
+ */
+ public function modReplace($dn, array $entry);
+
+ /**
+ * Delete attribute values from current attributes.
+ *
+ * @link http://php.net/manual/en/function.ldap-mod-del.php
+ *
+ * @param string $dn
+ * @param array $entry
+ *
+ * @return mixed
+ */
+ public function modDelete($dn, array $entry);
+
+ /**
+ * Send LDAP pagination control.
+ *
+ * @link http://php.net/manual/en/function.ldap-control-paged-result.php
+ *
+ * @param int $pageSize
+ * @param bool $isCritical
+ * @param string $cookie
+ *
+ * @return mixed
+ */
+ public function controlPagedResult($pageSize = 1000, $isCritical = false, $cookie = '');
+
+ /**
+ * Retrieve the LDAP pagination cookie.
+ *
+ * @link http://php.net/manual/en/function.ldap-control-paged-result-response.php
+ *
+ * @param $result
+ * @param string $cookie
+ *
+ * @return mixed
+ */
+ public function controlPagedResultResponse($result, &$cookie);
+
+ /**
+ * Frees up the memory allocated internally to store the result.
+ *
+ * @link https://www.php.net/manual/en/function.ldap-free-result.php
+ *
+ * @param resource $result
+ *
+ * @return bool
+ */
+ public function freeResult($result);
+
+ /**
+ * Returns the error number of the last command
+ * executed on the current connection.
+ *
+ * @link http://php.net/manual/en/function.ldap-errno.php
+ *
+ * @return int
+ */
+ public function errNo();
+
+ /**
+ * Returns the extended error string of the last command.
+ *
+ * @return string
+ */
+ public function getExtendedError();
+
+ /**
+ * Returns the extended error hex code of the last command.
+ *
+ * @return string|null
+ */
+ public function getExtendedErrorHex();
+
+ /**
+ * Returns the extended error code of the last command.
+ *
+ * @return string
+ */
+ public function getExtendedErrorCode();
+
+ /**
+ * Returns the error string of the specified
+ * error number.
+ *
+ * @link http://php.net/manual/en/function.ldap-err2str.php
+ *
+ * @param int $number
+ *
+ * @return string
+ */
+ public function err2Str($number);
+
+ /**
+ * Return the diagnostic Message.
+ *
+ * @return string
+ */
+ public function getDiagnosticMessage();
+
+ /**
+ * Extract the diagnostic code from the message.
+ *
+ * @param string $message
+ *
+ * @return string|bool
+ */
+ public function extractDiagnosticCode($message);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/DetailedError.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/DetailedError.php
new file mode 100644
index 0000000..d7554c6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/DetailedError.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace Adldap\Connections;
+
+class DetailedError
+{
+ /**
+ * The error code from ldap_errno.
+ *
+ * @var int|null
+ */
+ protected $errorCode;
+
+ /**
+ * The error message from ldap_error.
+ *
+ * @var string|null
+ */
+ protected $errorMessage;
+
+ /**
+ * The diagnostic message when retrieved after an ldap_error.
+ *
+ * @var string|null
+ */
+ protected $diagnosticMessage;
+
+ /**
+ * Constructor.
+ *
+ * @param int $errorCode
+ * @param string $errorMessage
+ * @param string $diagnosticMessage
+ */
+ public function __construct($errorCode, $errorMessage, $diagnosticMessage)
+ {
+ $this->errorCode = $errorCode;
+ $this->errorMessage = $errorMessage;
+ $this->diagnosticMessage = $diagnosticMessage;
+ }
+
+ /**
+ * Returns the LDAP error code.
+ *
+ * @return int
+ */
+ public function getErrorCode()
+ {
+ return $this->errorCode;
+ }
+
+ /**
+ * Returns the LDAP error message.
+ *
+ * @return string
+ */
+ public function getErrorMessage()
+ {
+ return $this->errorMessage;
+ }
+
+ /**
+ * Returns the LDAP diagnostic message.
+ *
+ * @return string
+ */
+ public function getDiagnosticMessage()
+ {
+ return $this->diagnosticMessage;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/Ldap.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/Ldap.php
new file mode 100644
index 0000000..2ce83fd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/Ldap.php
@@ -0,0 +1,545 @@
+<?php
+
+namespace Adldap\Connections;
+
+/**
+ * Class Ldap.
+ *
+ * A class that abstracts PHP's LDAP functions and stores the bound connection.
+ */
+class Ldap implements ConnectionInterface
+{
+ /**
+ * The connection name.
+ *
+ * @var string|null
+ */
+ protected $name;
+
+ /**
+ * The LDAP host that is currently connected.
+ *
+ * @var string|null
+ */
+ protected $host;
+
+ /**
+ * The active LDAP connection.
+ *
+ * @var resource
+ */
+ protected $connection;
+
+ /**
+ * The bound status of the connection.
+ *
+ * @var bool
+ */
+ protected $bound = false;
+
+ /**
+ * Whether the connection must be bound over SSL.
+ *
+ * @var bool
+ */
+ protected $useSSL = false;
+
+ /**
+ * Whether the connection must be bound over TLS.
+ *
+ * @var bool
+ */
+ protected $useTLS = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($name = null)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isUsingSSL()
+ {
+ return $this->useSSL;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isUsingTLS()
+ {
+ return $this->useTLS;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isBound()
+ {
+ return $this->bound;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function canChangePasswords()
+ {
+ return $this->isUsingSSL() || $this->isUsingTLS();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function ssl($enabled = true)
+ {
+ $this->useSSL = $enabled;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function tls($enabled = true)
+ {
+ $this->useTLS = $enabled;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getHost()
+ {
+ return $this->host;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConnection()
+ {
+ return $this->connection;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getEntries($searchResults)
+ {
+ return ldap_get_entries($this->connection, $searchResults);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFirstEntry($searchResults)
+ {
+ return ldap_first_entry($this->connection, $searchResults);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNextEntry($entry)
+ {
+ return ldap_next_entry($this->connection, $entry);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getAttributes($entry)
+ {
+ return ldap_get_attributes($this->connection, $entry);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function countEntries($searchResults)
+ {
+ return ldap_count_entries($this->connection, $searchResults);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function compare($dn, $attribute, $value)
+ {
+ return ldap_compare($this->connection, $dn, $attribute, $value);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLastError()
+ {
+ return ldap_error($this->connection);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDetailedError()
+ {
+ // If the returned error number is zero, the last LDAP operation
+ // succeeded. We won't return a detailed error.
+ if ($number = $this->errNo()) {
+ ldap_get_option($this->connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $message);
+
+ return new DetailedError($number, $this->err2Str($number), $message);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getValuesLen($entry, $attribute)
+ {
+ return ldap_get_values_len($this->connection, $entry, $attribute);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setOption($option, $value)
+ {
+ return ldap_set_option($this->connection, $option, $value);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setOptions(array $options = [])
+ {
+ foreach ($options as $option => $value) {
+ $this->setOption($option, $value);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setRebindCallback(callable $callback)
+ {
+ return ldap_set_rebind_proc($this->connection, $callback);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function startTLS()
+ {
+ try {
+ return ldap_start_tls($this->connection);
+ } catch (\ErrorException $e) {
+ throw new ConnectionException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function connect($hosts = [], $port = 389)
+ {
+ $this->host = $this->getConnectionString($hosts, $this->getProtocol(), $port);
+
+ // Reset the bound status if reinitializing the connection.
+ $this->bound = false;
+
+ return $this->connection = ldap_connect($this->host);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function close()
+ {
+ $connection = $this->connection;
+
+ $result = is_resource($connection) ? ldap_close($connection) : false;
+
+ $this->bound = false;
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function search($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0)
+ {
+ return ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function listing($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0)
+ {
+ return ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function read($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0)
+ {
+ return ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time);
+ }
+
+ /**
+ * Extract information from an LDAP result.
+ *
+ * @link https://www.php.net/manual/en/function.ldap-parse-result.php
+ *
+ * @param resource $result
+ * @param int $errorCode
+ * @param string $dn
+ * @param string $errorMessage
+ * @param array $referrals
+ * @param array $serverControls
+ *
+ * @return bool
+ */
+ public function parseResult($result, &$errorCode, &$dn, &$errorMessage, &$referrals, &$serverControls = [])
+ {
+ return $this->supportsServerControlsInMethods() && !empty($serverControls) ?
+ ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals, $serverControls) :
+ ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function bind($username, $password, $sasl = false)
+ {
+ // Prior to binding, we will upgrade our connectivity to TLS on our current
+ // connection and ensure we are not already bound before upgrading.
+ // This is to prevent subsequent upgrading on several binds.
+ if ($this->isUsingTLS() && !$this->isBound()) {
+ $this->startTLS();
+ }
+
+ if ($sasl) {
+ return $this->bound = ldap_sasl_bind($this->connection, null, null, 'GSSAPI');
+ }
+
+ return $this->bound = ldap_bind(
+ $this->connection,
+ $username,
+ html_entity_decode($password)
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add($dn, array $entry)
+ {
+ return ldap_add($this->connection, $dn, $entry);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete($dn)
+ {
+ return ldap_delete($this->connection, $dn);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rename($dn, $newRdn, $newParent, $deleteOldRdn = false)
+ {
+ return ldap_rename($this->connection, $dn, $newRdn, $newParent, $deleteOldRdn);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function modify($dn, array $entry)
+ {
+ return ldap_modify($this->connection, $dn, $entry);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function modifyBatch($dn, array $values)
+ {
+ return ldap_modify_batch($this->connection, $dn, $values);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function modAdd($dn, array $entry)
+ {
+ return ldap_mod_add($this->connection, $dn, $entry);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function modReplace($dn, array $entry)
+ {
+ return ldap_mod_replace($this->connection, $dn, $entry);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function modDelete($dn, array $entry)
+ {
+ return ldap_mod_del($this->connection, $dn, $entry);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function controlPagedResult($pageSize = 1000, $isCritical = false, $cookie = '')
+ {
+ return ldap_control_paged_result($this->connection, $pageSize, $isCritical, $cookie);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function controlPagedResultResponse($result, &$cookie)
+ {
+ return ldap_control_paged_result_response($this->connection, $result, $cookie);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function freeResult($result)
+ {
+ return ldap_free_result($result);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function errNo()
+ {
+ return ldap_errno($this->connection);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getExtendedError()
+ {
+ return $this->getDiagnosticMessage();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getExtendedErrorHex()
+ {
+ if (preg_match("/(?<=data\s).*?(?=\,)/", $this->getExtendedError(), $code)) {
+ return $code[0];
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getExtendedErrorCode()
+ {
+ return $this->extractDiagnosticCode($this->getExtendedError());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function err2Str($number)
+ {
+ return ldap_err2str($number);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDiagnosticMessage()
+ {
+ ldap_get_option($this->connection, LDAP_OPT_ERROR_STRING, $message);
+
+ return $message;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function extractDiagnosticCode($message)
+ {
+ preg_match('/^([\da-fA-F]+):/', $message, $matches);
+
+ return isset($matches[1]) ? $matches[1] : false;
+ }
+
+ /**
+ * Returns the LDAP protocol to utilize for the current connection.
+ *
+ * @return string
+ */
+ public function getProtocol()
+ {
+ return $this->isUsingSSL() ? $this::PROTOCOL_SSL : $this::PROTOCOL;
+ }
+
+ /**
+ * Determine if the current PHP version supports server controls.
+ *
+ * @return bool
+ */
+ public function supportsServerControlsInMethods()
+ {
+ return version_compare(PHP_VERSION, '7.3.0') >= 0;
+ }
+
+ /**
+ * Generates an LDAP connection string for each host given.
+ *
+ * @param string|array $hosts
+ * @param string $protocol
+ * @param string $port
+ *
+ * @return string
+ */
+ protected function getConnectionString($hosts, $protocol, $port)
+ {
+ // If we are using SSL and using the default port, we
+ // will override it to use the default SSL port.
+ if ($this->isUsingSSL() && $port == 389) {
+ $port = self::PORT_SSL;
+ }
+
+ // Normalize hosts into an array.
+ $hosts = is_array($hosts) ? $hosts : [$hosts];
+
+ $hosts = array_map(function ($host) use ($protocol, $port) {
+ return "{$protocol}{$host}:{$port}";
+ }, $hosts);
+
+ return implode(' ', $hosts);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/Provider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/Provider.php
new file mode 100644
index 0000000..c8db387
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/Provider.php
@@ -0,0 +1,291 @@
+<?php
+
+namespace Adldap\Connections;
+
+use Adldap\Adldap;
+use Adldap\Auth\Guard;
+use Adldap\Query\Cache;
+use InvalidArgumentException;
+use Adldap\Auth\GuardInterface;
+use Adldap\Schemas\ActiveDirectory;
+use Adldap\Schemas\SchemaInterface;
+use Psr\SimpleCache\CacheInterface;
+use Adldap\Models\Factory as ModelFactory;
+use Adldap\Query\Factory as SearchFactory;
+use Adldap\Configuration\DomainConfiguration;
+
+/**
+ * Class Provider.
+ *
+ * Contains the LDAP connection and domain configuration to
+ * instantiate factories for retrieving and creating
+ * LDAP records as well as authentication (binding).
+ */
+class Provider implements ProviderInterface
+{
+ /**
+ * The providers connection.
+ *
+ * @var ConnectionInterface
+ */
+ protected $connection;
+
+ /**
+ * The providers configuration.
+ *
+ * @var DomainConfiguration
+ */
+ protected $configuration;
+
+ /**
+ * The providers schema.
+ *
+ * @var SchemaInterface
+ */
+ protected $schema;
+
+ /**
+ * The providers auth guard instance.
+ *
+ * @var GuardInterface
+ */
+ protected $guard;
+
+ /**
+ * The providers cache instance.
+ *
+ * @var Cache|null
+ */
+ protected $cache;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($configuration = [], ConnectionInterface $connection = null)
+ {
+ $this->setConfiguration($configuration)
+ ->setConnection($connection);
+ }
+
+ /**
+ * Does nothing. Implemented in order to remain backwards compatible.
+ *
+ * @deprecated since v10.3.0
+ */
+ public function __destruct()
+ {
+ //
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setConfiguration($configuration = [])
+ {
+ if (is_array($configuration)) {
+ $configuration = new DomainConfiguration($configuration);
+ }
+
+ if ($configuration instanceof DomainConfiguration) {
+ $this->configuration = $configuration;
+
+ $schema = $configuration->get('schema');
+
+ // We will update our schema here when our configuration is set.
+ $this->setSchema(new $schema());
+
+ return $this;
+ }
+
+ $class = DomainConfiguration::class;
+
+ throw new InvalidArgumentException(
+ "Configuration must be array or instance of $class"
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setConnection(ConnectionInterface $connection = null)
+ {
+ // We will create a standard connection if one isn't given.
+ $this->connection = $connection ?: new Ldap();
+
+ // Prepare the connection.
+ $this->prepareConnection();
+
+ // Instantiate the LDAP connection.
+ $this->connection->connect(
+ $this->configuration->get('hosts'),
+ $this->configuration->get('port')
+ );
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setSchema(SchemaInterface $schema = null)
+ {
+ $this->schema = $schema ?: new ActiveDirectory();
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setGuard(GuardInterface $guard)
+ {
+ $this->guard = $guard;
+
+ return $this;
+ }
+
+ /**
+ * Sets the cache store.
+ *
+ * @param CacheInterface $store
+ *
+ * @return $this
+ */
+ public function setCache(CacheInterface $store)
+ {
+ $this->cache = new Cache($store);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfiguration()
+ {
+ return $this->configuration;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConnection()
+ {
+ return $this->connection;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSchema()
+ {
+ return $this->schema;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getGuard()
+ {
+ if (!$this->guard instanceof GuardInterface) {
+ $this->setGuard($this->getDefaultGuard($this->connection, $this->configuration));
+ }
+
+ return $this->guard;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDefaultGuard(ConnectionInterface $connection, DomainConfiguration $configuration)
+ {
+ $guard = new Guard($connection, $configuration);
+
+ $guard->setDispatcher(Adldap::getEventDispatcher());
+
+ return $guard;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function make()
+ {
+ return new ModelFactory(
+ $this->search()->newQuery()
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function search()
+ {
+ $factory = new SearchFactory(
+ $this->connection,
+ $this->schema,
+ $this->configuration->get('base_dn')
+ );
+
+ if ($this->cache) {
+ $factory->setCache($this->cache);
+ }
+
+ return $factory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function auth()
+ {
+ return $this->getGuard();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function connect($username = null, $password = null)
+ {
+ // Get the default guard instance.
+ $guard = $this->getGuard();
+
+ if (is_null($username) && is_null($password)) {
+ // If both the username and password are null, we'll connect to the server
+ // using the configured administrator username and password.
+ $guard->bindAsAdministrator();
+ } else {
+ // Bind to the server with the specified username and password otherwise.
+ $guard->bind($username, $password);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Prepares the connection by setting configured parameters.
+ *
+ * @throws \Adldap\Configuration\ConfigurationException When configuration options requested do not exist
+ *
+ * @return void
+ */
+ protected function prepareConnection()
+ {
+ if ($this->configuration->get('use_ssl')) {
+ $this->connection->ssl();
+ } elseif ($this->configuration->get('use_tls')) {
+ $this->connection->tls();
+ }
+
+ $options = array_replace(
+ $this->configuration->get('custom_options'),
+ [
+ LDAP_OPT_PROTOCOL_VERSION => $this->configuration->get('version'),
+ LDAP_OPT_NETWORK_TIMEOUT => $this->configuration->get('timeout'),
+ LDAP_OPT_REFERRALS => $this->configuration->get('follow_referrals'),
+ ]
+ );
+
+ $this->connection->setOptions($options);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/ProviderInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/ProviderInterface.php
new file mode 100644
index 0000000..20749a7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Connections/ProviderInterface.php
@@ -0,0 +1,129 @@
+<?php
+
+namespace Adldap\Connections;
+
+use Adldap\Auth\GuardInterface;
+use Adldap\Schemas\SchemaInterface;
+use Adldap\Configuration\DomainConfiguration;
+
+interface ProviderInterface
+{
+ /**
+ * Constructor.
+ *
+ * @param array|DomainConfiguration $configuration
+ * @param ConnectionInterface $connection
+ */
+ public function __construct($configuration, ConnectionInterface $connection);
+
+ /**
+ * Returns the current connection instance.
+ *
+ * @return ConnectionInterface
+ */
+ public function getConnection();
+
+ /**
+ * Returns the current configuration instance.
+ *
+ * @return DomainConfiguration
+ */
+ public function getConfiguration();
+
+ /**
+ * Returns the current Guard instance.
+ *
+ * @return \Adldap\Auth\Guard
+ */
+ public function getGuard();
+
+ /**
+ * Returns a new default Guard instance.
+ *
+ * @param ConnectionInterface $connection
+ * @param DomainConfiguration $configuration
+ *
+ * @return \Adldap\Auth\Guard
+ */
+ public function getDefaultGuard(ConnectionInterface $connection, DomainConfiguration $configuration);
+
+ /**
+ * Sets the current connection.
+ *
+ * @param ConnectionInterface $connection
+ *
+ * @return $this
+ */
+ public function setConnection(ConnectionInterface $connection = null);
+
+ /**
+ * Sets the current configuration.
+ *
+ * @param DomainConfiguration|array $configuration
+ *
+ * @throws \Adldap\Configuration\ConfigurationException
+ */
+ public function setConfiguration($configuration = []);
+
+ /**
+ * Sets the current LDAP attribute schema.
+ *
+ * @param SchemaInterface|null $schema
+ *
+ * @return $this
+ */
+ public function setSchema(SchemaInterface $schema = null);
+
+ /**
+ * Returns the current LDAP attribute schema.
+ *
+ * @return SchemaInterface
+ */
+ public function getSchema();
+
+ /**
+ * Sets the current Guard instance.
+ *
+ * @param GuardInterface $guard
+ *
+ * @return $this
+ */
+ public function setGuard(GuardInterface $guard);
+
+ /**
+ * Returns a new Model factory instance.
+ *
+ * @return \Adldap\Models\Factory
+ */
+ public function make();
+
+ /**
+ * Returns a new Search factory instance.
+ *
+ * @return \Adldap\Query\Factory
+ */
+ public function search();
+
+ /**
+ * Returns a new Auth Guard instance.
+ *
+ * @return \Adldap\Auth\Guard
+ */
+ public function auth();
+
+ /**
+ * Connects and Binds to the Domain Controller.
+ *
+ * If no username or password is specified, then the
+ * configured administrator credentials are used.
+ *
+ * @param string|null $username
+ * @param string|null $password
+ *
+ * @throws \Adldap\Auth\BindException If binding to the LDAP server fails.
+ * @throws ConnectionException If upgrading the connection to TLS fails
+ *
+ * @return ProviderInterface
+ */
+ public function connect($username = null, $password = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Events/Dispatcher.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Events/Dispatcher.php
new file mode 100644
index 0000000..f81f478
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Events/Dispatcher.php
@@ -0,0 +1,320 @@
+<?php
+
+namespace Adldap\Events;
+
+use Illuminate\Support\Arr;
+
+/**
+ * Class Dispatcher.
+ *
+ * Handles event listening and dispatching.
+ *
+ * This code was taken out of the Laravel Framework core
+ * with broadcasting and queuing omitted to remove
+ * an extra dependency that would be required.
+ *
+ * @author Taylor Otwell
+ *
+ * @see https://github.com/laravel/framework
+ */
+class Dispatcher implements DispatcherInterface
+{
+ /**
+ * The registered event listeners.
+ *
+ * @var array
+ */
+ protected $listeners = [];
+
+ /**
+ * The wildcard listeners.
+ *
+ * @var array
+ */
+ protected $wildcards = [];
+
+ /**
+ * The cached wildcard listeners.
+ *
+ * @var array
+ */
+ protected $wildcardsCache = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function listen($events, $listener)
+ {
+ foreach ((array) $events as $event) {
+ if (strpos($event, '*') !== false) {
+ $this->setupWildcardListen($event, $listener);
+ } else {
+ $this->listeners[$event][] = $this->makeListener($listener);
+ }
+ }
+ }
+
+ /**
+ * Setup a wildcard listener callback.
+ *
+ * @param string $event
+ * @param mixed $listener
+ *
+ * @return void
+ */
+ protected function setupWildcardListen($event, $listener)
+ {
+ $this->wildcards[$event][] = $this->makeListener($listener, true);
+
+ $this->wildcardsCache = [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasListeners($eventName)
+ {
+ return isset($this->listeners[$eventName]) || isset($this->wildcards[$eventName]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function until($event, $payload = [])
+ {
+ return $this->dispatch($event, $payload, true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function fire($event, $payload = [], $halt = false)
+ {
+ return $this->dispatch($event, $payload, $halt);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dispatch($event, $payload = [], $halt = false)
+ {
+ // When the given "event" is actually an object we will assume it is an event
+ // object and use the class as the event name and this event itself as the
+ // payload to the handler, which makes object based events quite simple.
+ list($event, $payload) = $this->parseEventAndPayload(
+ $event,
+ $payload
+ );
+
+ $responses = [];
+
+ foreach ($this->getListeners($event) as $listener) {
+ $response = $listener($event, $payload);
+
+ // If a response is returned from the listener and event halting is enabled
+ // we will just return this response, and not call the rest of the event
+ // listeners. Otherwise we will add the response on the response list.
+ if ($halt && !is_null($response)) {
+ return $response;
+ }
+
+ // If a boolean false is returned from a listener, we will stop propagating
+ // the event to any further listeners down in the chain, else we keep on
+ // looping through the listeners and firing every one in our sequence.
+ if ($response === false) {
+ break;
+ }
+
+ $responses[] = $response;
+ }
+
+ return $halt ? null : $responses;
+ }
+
+ /**
+ * Parse the given event and payload and prepare them for dispatching.
+ *
+ * @param mixed $event
+ * @param mixed $payload
+ *
+ * @return array
+ */
+ protected function parseEventAndPayload($event, $payload)
+ {
+ if (is_object($event)) {
+ list($payload, $event) = [[$event], get_class($event)];
+ }
+
+ return [$event, Arr::wrap($payload)];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getListeners($eventName)
+ {
+ $listeners = $this->listeners[$eventName] ?? [];
+
+ $listeners = array_merge(
+ $listeners,
+ $this->wildcardsCache[$eventName] ?? $this->getWildcardListeners($eventName)
+ );
+
+ return class_exists($eventName, false)
+ ? $this->addInterfaceListeners($eventName, $listeners)
+ : $listeners;
+ }
+
+ /**
+ * Get the wildcard listeners for the event.
+ *
+ * @param string $eventName
+ *
+ * @return array
+ */
+ protected function getWildcardListeners($eventName)
+ {
+ $wildcards = [];
+
+ foreach ($this->wildcards as $key => $listeners) {
+ if ($this->wildcardContainsEvent($key, $eventName)) {
+ $wildcards = array_merge($wildcards, $listeners);
+ }
+ }
+
+ return $this->wildcardsCache[$eventName] = $wildcards;
+ }
+
+ /**
+ * Determine if the wildcard matches or contains the given event.
+ *
+ * This function is a direct excerpt from Laravel's Str::is().
+ *
+ * @param string $wildcard
+ * @param string $eventName
+ *
+ * @return bool
+ */
+ protected function wildcardContainsEvent($wildcard, $eventName)
+ {
+ $patterns = Arr::wrap($wildcard);
+
+ if (empty($patterns)) {
+ return false;
+ }
+
+ foreach ($patterns as $pattern) {
+ // If the given event is an exact match we can of course return true right
+ // from the beginning. Otherwise, we will translate asterisks and do an
+ // actual pattern match against the two strings to see if they match.
+ if ($pattern == $eventName) {
+ return true;
+ }
+
+ $pattern = preg_quote($pattern, '#');
+
+ // Asterisks are translated into zero-or-more regular expression wildcards
+ // to make it convenient to check if the strings starts with the given
+ // pattern such as "library/*", making any string check convenient.
+ $pattern = str_replace('\*', '.*', $pattern);
+
+ if (preg_match('#^'.$pattern.'\z#u', $eventName) === 1) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Add the listeners for the event's interfaces to the given array.
+ *
+ * @param string $eventName
+ * @param array $listeners
+ *
+ * @return array
+ */
+ protected function addInterfaceListeners($eventName, array $listeners = [])
+ {
+ foreach (class_implements($eventName) as $interface) {
+ if (isset($this->listeners[$interface])) {
+ foreach ($this->listeners[$interface] as $names) {
+ $listeners = array_merge($listeners, (array) $names);
+ }
+ }
+ }
+
+ return $listeners;
+ }
+
+ /**
+ * Register an event listener with the dispatcher.
+ *
+ * @param \Closure|string $listener
+ * @param bool $wildcard
+ *
+ * @return \Closure
+ */
+ public function makeListener($listener, $wildcard = false)
+ {
+ if (is_string($listener)) {
+ return $this->createClassListener($listener, $wildcard);
+ }
+
+ return function ($event, $payload) use ($listener, $wildcard) {
+ if ($wildcard) {
+ return $listener($event, $payload);
+ }
+
+ return $listener(...array_values($payload));
+ };
+ }
+
+ /**
+ * Create a class based listener.
+ *
+ * @param string $listener
+ * @param bool $wildcard
+ *
+ * @return \Closure
+ */
+ protected function createClassListener($listener, $wildcard = false)
+ {
+ return function ($event, $payload) use ($listener, $wildcard) {
+ if ($wildcard) {
+ return call_user_func($this->parseListenerCallback($listener), $event, $payload);
+ }
+
+ return call_user_func_array(
+ $this->parseListenerCallback($listener),
+ $payload
+ );
+ };
+ }
+
+ /**
+ * Parse the class listener into class and method.
+ *
+ * @param string $listener
+ *
+ * @return array
+ */
+ protected function parseListenerCallback($listener)
+ {
+ return strpos($listener, '@') !== false ?
+ explode('@', $listener, 2) :
+ [$listener, 'handle'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function forget($event)
+ {
+ if (strpos($event, '*') !== false) {
+ unset($this->wildcards[$event]);
+ } else {
+ unset($this->listeners[$event]);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Events/DispatcherInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Events/DispatcherInterface.php
new file mode 100644
index 0000000..e014543
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Events/DispatcherInterface.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Adldap\Events;
+
+interface DispatcherInterface
+{
+ /**
+ * Register an event listener with the dispatcher.
+ *
+ * @param string|array $events
+ * @param mixed $listener
+ *
+ * @return void
+ */
+ public function listen($events, $listener);
+
+ /**
+ * Determine if a given event has listeners.
+ *
+ * @param string $eventName
+ *
+ * @return bool
+ */
+ public function hasListeners($eventName);
+
+ /**
+ * Fire an event until the first non-null response is returned.
+ *
+ * @param string|object $event
+ * @param mixed $payload
+ *
+ * @return array|null
+ */
+ public function until($event, $payload = []);
+
+ /**
+ * Fire an event and call the listeners.
+ *
+ * @param string|object $event
+ * @param mixed $payload
+ * @param bool $halt
+ *
+ * @return mixed
+ */
+ public function fire($event, $payload = [], $halt = false);
+
+ /**
+ * Fire an event and call the listeners.
+ *
+ * @param string|object $event
+ * @param mixed $payload
+ * @param bool $halt
+ *
+ * @return array|null
+ */
+ public function dispatch($event, $payload = [], $halt = false);
+
+ /**
+ * Get all of the listeners for a given event name.
+ *
+ * @param string $eventName
+ *
+ * @return array
+ */
+ public function getListeners($eventName);
+
+ /**
+ * Remove a set of listeners from the dispatcher.
+ *
+ * @param string $event
+ *
+ * @return void
+ */
+ public function forget($event);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Events/DispatchesEvents.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Events/DispatchesEvents.php
new file mode 100644
index 0000000..f530ba4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Events/DispatchesEvents.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Adldap\Events;
+
+trait DispatchesEvents
+{
+ /**
+ * The event dispatcher instance.
+ *
+ * @var DispatcherInterface
+ */
+ protected static $dispatcher;
+
+ /**
+ * Get the event dispatcher instance.
+ *
+ * @return DispatcherInterface
+ */
+ public static function getEventDispatcher()
+ {
+ // If no event dispatcher has been set, well instantiate and
+ // set one here. This will be our singleton instance.
+ if (!isset(static::$dispatcher)) {
+ static::setEventDispatcher(new Dispatcher());
+ }
+
+ return static::$dispatcher;
+ }
+
+ /**
+ * Set the event dispatcher instance.
+ *
+ * @param DispatcherInterface $dispatcher
+ *
+ * @return void
+ */
+ public static function setEventDispatcher(DispatcherInterface $dispatcher)
+ {
+ static::$dispatcher = $dispatcher;
+ }
+
+ /**
+ * Unset the event dispatcher instance.
+ *
+ * @return void
+ */
+ public static function unsetEventDispatcher()
+ {
+ static::$dispatcher = null;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Log/EventLogger.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Log/EventLogger.php
new file mode 100644
index 0000000..37d36b8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Log/EventLogger.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace Adldap\Log;
+
+use ReflectionClass;
+use Psr\Log\LoggerInterface;
+use Adldap\Auth\Events\Failed;
+use Adldap\Auth\Events\Event as AuthEvent;
+use Adldap\Models\Events\Event as ModelEvent;
+use Adldap\Query\Events\QueryExecuted as QueryEvent;
+
+class EventLogger
+{
+ /**
+ * The logger instance.
+ *
+ * @var LoggerInterface|null
+ */
+ protected $logger;
+
+ /**
+ * Constructor.
+ *
+ * @param LoggerInterface $logger
+ */
+ public function __construct(LoggerInterface $logger = null)
+ {
+ $this->logger = $logger;
+ }
+
+ /**
+ * Logs the given event.
+ *
+ * @param mixed $event
+ */
+ public function log($event)
+ {
+ if ($event instanceof AuthEvent) {
+ $this->auth($event);
+ } elseif ($event instanceof ModelEvent) {
+ $this->model($event);
+ } elseif ($event instanceof QueryEvent) {
+ $this->query($event);
+ }
+ }
+
+ /**
+ * Logs an authentication event.
+ *
+ * @param AuthEvent $event
+ *
+ * @return void
+ */
+ public function auth(AuthEvent $event)
+ {
+ if (isset($this->logger)) {
+ $connection = $event->getConnection();
+
+ $message = "LDAP ({$connection->getHost()})"
+ ." - Connection: {$connection->getName()}"
+ ." - Operation: {$this->getOperationName($event)}"
+ ." - Username: {$event->getUsername()}";
+
+ $result = null;
+ $type = 'info';
+
+ if (is_a($event, Failed::class)) {
+ $type = 'warning';
+ $result = " - Reason: {$connection->getLastError()}";
+ }
+
+ $this->logger->$type($message.$result);
+ }
+ }
+
+ /**
+ * Logs a model event.
+ *
+ * @param ModelEvent $event
+ *
+ * @return void
+ */
+ public function model(ModelEvent $event)
+ {
+ if (isset($this->logger)) {
+ $model = $event->getModel();
+
+ $on = get_class($model);
+
+ $connection = $model->getQuery()->getConnection();
+
+ $message = "LDAP ({$connection->getHost()})"
+ ." - Connection: {$connection->getName()}"
+ ." - Operation: {$this->getOperationName($event)}"
+ ." - On: {$on}"
+ ." - Distinguished Name: {$model->getDn()}";
+
+ $this->logger->info($message);
+ }
+ }
+
+ /**
+ * Logs a query event.
+ *
+ * @param QueryEvent $event
+ *
+ * @return void
+ */
+ public function query(QueryEvent $event)
+ {
+ if (isset($this->logger)) {
+ $query = $event->getQuery();
+
+ $connection = $query->getConnection();
+
+ $selected = implode(',', $query->getSelects());
+
+ $message = "LDAP ({$connection->getHost()})"
+ ." - Connection: {$connection->getName()}"
+ ." - Operation: {$this->getOperationName($event)}"
+ ." - Base DN: {$query->getDn()}"
+ ." - Filter: {$query->getUnescapedQuery()}"
+ ." - Selected: ({$selected})"
+ ." - Time Elapsed: {$event->getTime()}";
+
+ $this->logger->info($message);
+ }
+ }
+
+ /**
+ * Returns the operational name of the given event.
+ *
+ * @param mixed $event
+ *
+ * @return string
+ */
+ protected function getOperationName($event)
+ {
+ return (new ReflectionClass($event))->getShortName();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Log/LogsInformation.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Log/LogsInformation.php
new file mode 100644
index 0000000..d6f5191
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Log/LogsInformation.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Adldap\Log;
+
+use Psr\Log\LoggerInterface;
+
+trait LogsInformation
+{
+ /**
+ * The logger instance.
+ *
+ * @var LoggerInterface|null
+ */
+ protected static $logger;
+
+ /**
+ * Get the logger instance.
+ *
+ * @return LoggerInterface|null
+ */
+ public static function getLogger()
+ {
+ return static::$logger;
+ }
+
+ /**
+ * Set the logger instance.
+ *
+ * @param LoggerInterface $logger
+ *
+ * @return void
+ */
+ public static function setLogger(LoggerInterface $logger)
+ {
+ static::$logger = $logger;
+ }
+
+ /**
+ * Unset the logger instance.
+ *
+ * @return void
+ */
+ public static function unsetLogger()
+ {
+ static::$logger = null;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/AccountControl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/AccountControl.php
new file mode 100644
index 0000000..89fd8a4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/AccountControl.php
@@ -0,0 +1,458 @@
+<?php
+
+namespace Adldap\Models\Attributes;
+
+use ReflectionClass;
+
+/**
+ * The Account Control class.
+ *
+ * This class is for easily building a user account control value.
+ *
+ * @link https://support.microsoft.com/en-us/kb/305144
+ */
+class AccountControl
+{
+ const SCRIPT = 1;
+
+ const ACCOUNTDISABLE = 2;
+
+ const HOMEDIR_REQUIRED = 8;
+
+ const LOCKOUT = 16;
+
+ const PASSWD_NOTREQD = 32;
+
+ const ENCRYPTED_TEXT_PWD_ALLOWED = 128;
+
+ const TEMP_DUPLICATE_ACCOUNT = 256;
+
+ const NORMAL_ACCOUNT = 512;
+
+ const INTERDOMAIN_TRUST_ACCOUNT = 2048;
+
+ const WORKSTATION_TRUST_ACCOUNT = 4096;
+
+ const SERVER_TRUST_ACCOUNT = 8192;
+
+ const DONT_EXPIRE_PASSWORD = 65536;
+
+ const MNS_LOGON_ACCOUNT = 131072;
+
+ const SMARTCARD_REQUIRED = 262144;
+
+ const TRUSTED_FOR_DELEGATION = 524288;
+
+ const NOT_DELEGATED = 1048576;
+
+ const USE_DES_KEY_ONLY = 2097152;
+
+ const DONT_REQ_PREAUTH = 4194304;
+
+ const PASSWORD_EXPIRED = 8388608;
+
+ const TRUSTED_TO_AUTH_FOR_DELEGATION = 16777216;
+
+ const PARTIAL_SECRETS_ACCOUNT = 67108864;
+
+ /**
+ * Stores the values to be added together to
+ * build the user account control integer.
+ *
+ * @var array
+ */
+ protected $values = [];
+
+ /**
+ * Constructor.
+ *
+ * @param int $flag
+ */
+ public function __construct($flag = null)
+ {
+ if (!is_null($flag)) {
+ $this->apply($flag);
+ }
+ }
+
+ /**
+ * Get the value when casted to string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return (string) $this->getValue();
+ }
+
+ /**
+ * Get the value when casted to int.
+ *
+ * @return int
+ */
+ public function __toInt()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Add the value to the account control values.
+ *
+ * @param int $value
+ *
+ * @return AccountControl
+ */
+ public function add($value)
+ {
+ // Use the value as a key so if the same value
+ // is used, it will always be overwritten
+ $this->values[$value] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Remove the value from the account control.
+ *
+ * @param int $value
+ *
+ * @return $this
+ */
+ public function remove($value)
+ {
+ unset($this->values[$value]);
+
+ return $this;
+ }
+
+ /**
+ * Extract and apply the flag.
+ *
+ * @param int $flag
+ */
+ public function apply($flag)
+ {
+ $this->setValues($this->extractFlags($flag));
+ }
+
+ /**
+ * Determine if the current AccountControl object contains the given UAC flag(s).
+ *
+ * @param int $flag
+ *
+ * @return bool
+ */
+ public function has($flag)
+ {
+ // We'll extract the given flag into an array of possible flags, and
+ // see if our AccountControl object contains any of them.
+ $flagsUsed = array_intersect($this->extractFlags($flag), $this->values);
+
+ return in_array($flag, $flagsUsed);
+ }
+
+ /**
+ * The logon script will be run.
+ *
+ * @return AccountControl
+ */
+ public function runLoginScript()
+ {
+ return $this->add(static::SCRIPT);
+ }
+
+ /**
+ * The user account is locked.
+ *
+ * @return AccountControl
+ */
+ public function accountIsLocked()
+ {
+ return $this->add(static::LOCKOUT);
+ }
+
+ /**
+ * The user account is disabled.
+ *
+ * @return AccountControl
+ */
+ public function accountIsDisabled()
+ {
+ return $this->add(static::ACCOUNTDISABLE);
+ }
+
+ /**
+ * This is an account for users whose primary account is in another domain.
+ *
+ * This account provides user access to this domain, but not to any domain that
+ * trusts this domain. This is sometimes referred to as a local user account.
+ *
+ * @return AccountControl
+ */
+ public function accountIsTemporary()
+ {
+ return $this->add(static::TEMP_DUPLICATE_ACCOUNT);
+ }
+
+ /**
+ * This is a default account type that represents a typical user.
+ *
+ * @return AccountControl
+ */
+ public function accountIsNormal()
+ {
+ return $this->add(static::NORMAL_ACCOUNT);
+ }
+
+ /**
+ * This is a permit to trust an account for a system domain that trusts other domains.
+ *
+ * @return AccountControl
+ */
+ public function accountIsForInterdomain()
+ {
+ return $this->add(static::INTERDOMAIN_TRUST_ACCOUNT);
+ }
+
+ /**
+ * This is a computer account for a computer that is running Microsoft
+ * Windows NT 4.0 Workstation, Microsoft Windows NT 4.0 Server, Microsoft
+ * Windows 2000 Professional, or Windows 2000 Server and is a member of this domain.
+ *
+ * @return AccountControl
+ */
+ public function accountIsForWorkstation()
+ {
+ return $this->add(static::WORKSTATION_TRUST_ACCOUNT);
+ }
+
+ /**
+ * This is a computer account for a domain controller that is a member of this domain.
+ *
+ * @return AccountControl
+ */
+ public function accountIsForServer()
+ {
+ return $this->add(static::SERVER_TRUST_ACCOUNT);
+ }
+
+ /**
+ * This is an MNS logon account.
+ *
+ * @return AccountControl
+ */
+ public function accountIsMnsLogon()
+ {
+ return $this->add(static::MNS_LOGON_ACCOUNT);
+ }
+
+ /**
+ * (Windows 2000/Windows Server 2003) This account does
+ * not require Kerberos pre-authentication for logging on.
+ *
+ * @return AccountControl
+ */
+ public function accountDoesNotRequirePreAuth()
+ {
+ return $this->add(static::DONT_REQ_PREAUTH);
+ }
+
+ /**
+ * When this flag is set, it forces the user to log on by using a smart card.
+ *
+ * @return AccountControl
+ */
+ public function accountRequiresSmartCard()
+ {
+ return $this->add(static::SMARTCARD_REQUIRED);
+ }
+
+ /**
+ * (Windows Server 2008/Windows Server 2008 R2) The account is a read-only domain controller (RODC).
+ *
+ * This is a security-sensitive setting. Removing this setting from an RODC compromises security on that server.
+ *
+ * @return AccountControl
+ */
+ public function accountIsReadOnly()
+ {
+ return $this->add(static::PARTIAL_SECRETS_ACCOUNT);
+ }
+
+ /**
+ * The home folder is required.
+ *
+ * @return AccountControl
+ */
+ public function homeFolderIsRequired()
+ {
+ return $this->add(static::HOMEDIR_REQUIRED);
+ }
+
+ /**
+ * No password is required.
+ *
+ * @return AccountControl
+ */
+ public function passwordIsNotRequired()
+ {
+ return $this->add(static::PASSWD_NOTREQD);
+ }
+
+ /**
+ * The user cannot change the password. This is a permission on the user's object.
+ *
+ * For information about how to programmatically set this permission, visit the following link:
+ *
+ * @link http://msdn2.microsoft.com/en-us/library/aa746398.aspx
+ *
+ * @return AccountControl
+ */
+ public function passwordCannotBeChanged()
+ {
+ return $this->add(static::PASSWD_NOTREQD);
+ }
+
+ /**
+ * Represents the password, which should never expire on the account.
+ *
+ * @return AccountControl
+ */
+ public function passwordDoesNotExpire()
+ {
+ return $this->add(static::DONT_EXPIRE_PASSWORD);
+ }
+
+ /**
+ * (Windows 2000/Windows Server 2003) The user's password has expired.
+ *
+ * @return AccountControl
+ */
+ public function passwordIsExpired()
+ {
+ return $this->add(static::PASSWORD_EXPIRED);
+ }
+
+ /**
+ * The user can send an encrypted password.
+ *
+ * @return AccountControl
+ */
+ public function allowEncryptedTextPassword()
+ {
+ return $this->add(static::ENCRYPTED_TEXT_PWD_ALLOWED);
+ }
+
+ /**
+ * When this flag is set, the service account (the user or computer account)
+ * under which a service runs is trusted for Kerberos delegation.
+ *
+ * Any such service can impersonate a client requesting the service.
+ *
+ * To enable a service for Kerberos delegation, you must set this
+ * flag on the userAccountControl property of the service account.
+ *
+ * @return AccountControl
+ */
+ public function trustForDelegation()
+ {
+ return $this->add(static::TRUSTED_FOR_DELEGATION);
+ }
+
+ /**
+ * (Windows 2000/Windows Server 2003) The account is enabled for delegation.
+ *
+ * This is a security-sensitive setting. Accounts that have this option enabled
+ * should be tightly controlled. This setting lets a service that runs under the
+ * account assume a client's identity and authenticate as that user to other remote
+ * servers on the network.
+ *
+ * @return AccountControl
+ */
+ public function trustToAuthForDelegation()
+ {
+ return $this->add(static::TRUSTED_TO_AUTH_FOR_DELEGATION);
+ }
+
+ /**
+ * When this flag is set, the security context of the user is not delegated to a
+ * service even if the service account is set as trusted for Kerberos delegation.
+ *
+ * @return AccountControl
+ */
+ public function doNotTrustForDelegation()
+ {
+ return $this->add(static::NOT_DELEGATED);
+ }
+
+ /**
+ * (Windows 2000/Windows Server 2003) Restrict this principal to
+ * use only Data Encryption Standard (DES) encryption types for keys.
+ *
+ * @return AccountControl
+ */
+ public function useDesKeyOnly()
+ {
+ return $this->add(static::USE_DES_KEY_ONLY);
+ }
+
+ /**
+ * Get the account control value.
+ *
+ * @return int
+ */
+ public function getValue()
+ {
+ return array_sum($this->values);
+ }
+
+ /**
+ * Get the account control flag values.
+ *
+ * @return array
+ */
+ public function getValues()
+ {
+ return $this->values;
+ }
+
+ /**
+ * Set the account control values.
+ *
+ * @param array $flags
+ */
+ public function setValues(array $flags)
+ {
+ $this->values = $flags;
+ }
+
+ /**
+ * Get all possible account control flags.
+ *
+ * @return array
+ */
+ public function getAllFlags()
+ {
+ return (new ReflectionClass(__CLASS__))->getConstants();
+ }
+
+ /**
+ * Extracts the given flag into an array of flags used.
+ *
+ * @param int $flag
+ *
+ * @return array
+ */
+ public function extractFlags($flag)
+ {
+ $flags = [];
+
+ for ($i = 0; $i <= 26; $i++) {
+ if ((int) $flag & (1 << $i)) {
+ $flags[1 << $i] = 1 << $i;
+ }
+ }
+
+ return $flags;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/DistinguishedName.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/DistinguishedName.php
new file mode 100644
index 0000000..e610dbf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/DistinguishedName.php
@@ -0,0 +1,312 @@
+<?php
+
+namespace Adldap\Models\Attributes;
+
+use Adldap\Utilities;
+
+class DistinguishedName
+{
+ /**
+ * The distinguished name components (in order of assembly).
+ *
+ * @var array
+ */
+ protected $components = [
+ 'cn' => [],
+ 'uid' => [],
+ 'ou' => [],
+ 'dc' => [],
+ 'o' => [],
+ ];
+
+ /**
+ * Constructor.
+ *
+ * @param mixed $baseDn
+ */
+ public function __construct($baseDn = null)
+ {
+ $this->setBase($baseDn);
+ }
+
+ /**
+ * Returns the complete distinguished name.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->get();
+ }
+
+ /**
+ * Returns the complete distinguished name by assembling the RDN components.
+ *
+ * @return string
+ */
+ public function get()
+ {
+ $components = [];
+
+ // We'll go through each component type and assemble its RDN.
+ foreach ($this->components as $component => $values) {
+ array_map(function ($value) use ($component, &$components) {
+ // Assemble the component and escape the value.
+ $components[] = sprintf('%s=%s', $component, ldap_escape($value, '', 2));
+ }, $values);
+ }
+
+ return implode(',', $components);
+ }
+
+ /**
+ * Adds a domain component.
+ *
+ * @param string $dc
+ *
+ * @return DistinguishedName
+ */
+ public function addDc($dc)
+ {
+ $this->addComponent('dc', $dc);
+
+ return $this;
+ }
+
+ /**
+ * Removes a domain component.
+ *
+ * @param string $dc
+ *
+ * @return DistinguishedName
+ */
+ public function removeDc($dc)
+ {
+ $this->removeComponent('dc', $dc);
+
+ return $this;
+ }
+
+ /**
+ * Adds an organization name.
+ *
+ * @param string $o
+ *
+ * @return $this
+ */
+ public function addO($o)
+ {
+ $this->addComponent('o', $o);
+
+ return $this;
+ }
+
+ /**
+ * Removes an organization name.
+ *
+ * @param string $o
+ *
+ * @return DistinguishedName
+ */
+ public function removeO($o)
+ {
+ $this->removeComponent('o', $o);
+
+ return $this;
+ }
+
+ /**
+ * Add a user identifier.
+ *
+ * @param string $uid
+ *
+ * @return DistinguishedName
+ */
+ public function addUid($uid)
+ {
+ $this->addComponent('uid', $uid);
+
+ return $this;
+ }
+
+ /**
+ * Removes a user identifier.
+ *
+ * @param string $uid
+ *
+ * @return DistinguishedName
+ */
+ public function removeUid($uid)
+ {
+ $this->removeComponent('uid', $uid);
+
+ return $this;
+ }
+
+ /**
+ * Adds a common name.
+ *
+ * @param string $cn
+ *
+ * @return DistinguishedName
+ */
+ public function addCn($cn)
+ {
+ $this->addComponent('cn', $cn);
+
+ return $this;
+ }
+
+ /**
+ * Removes a common name.
+ *
+ * @param string $cn
+ *
+ * @return DistinguishedName
+ */
+ public function removeCn($cn)
+ {
+ $this->removeComponent('cn', $cn);
+
+ return $this;
+ }
+
+ /**
+ * Adds an organizational unit.
+ *
+ * @param string $ou
+ *
+ * @return DistinguishedName
+ */
+ public function addOu($ou)
+ {
+ $this->addComponent('ou', $ou);
+
+ return $this;
+ }
+
+ /**
+ * Removes an organizational unit.
+ *
+ * @param string $ou
+ *
+ * @return DistinguishedName
+ */
+ public function removeOu($ou)
+ {
+ $this->removeComponent('ou', $ou);
+
+ return $this;
+ }
+
+ /**
+ * Sets the base RDN of the distinguished name.
+ *
+ * @param string|DistinguishedName $base
+ *
+ * @return DistinguishedName
+ */
+ public function setBase($base)
+ {
+ // Typecast base to string in case we've been given
+ // an instance of the distinguished name object.
+ $base = (string) $base;
+
+ // If the base DN isn't null we'll try to explode it.
+ $base = Utilities::explodeDn($base, false) ?: [];
+
+ // Remove the count key from the exploded distinguished name.
+ unset($base['count']);
+
+ foreach ($base as $key => $rdn) {
+ // We'll break the RDN into pieces
+ $pieces = explode('=', $rdn) ?: [];
+
+ // If there's exactly 2 pieces, then we can work with it.
+ if (count($pieces) === 2) {
+ $attribute = ucfirst(strtolower($pieces[0]));
+
+ $method = 'add'.$attribute;
+
+ if (method_exists($this, $method)) {
+ // We see what type of RDN it is and add each accordingly.
+ call_user_func_array([$this, $method], [$pieces[1]]);
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns an array of all components in the distinguished name.
+ *
+ * If a component name is given ('cn', 'dc' for example) then
+ * the values of that component will be returned.
+ *
+ * @param string|null $component The component to retrieve values of
+ *
+ * @return array
+ */
+ public function getComponents($component = null)
+ {
+ if (is_null($component)) {
+ return $this->components;
+ }
+
+ $this->validateComponentExists($component);
+
+ return $this->components[$component];
+ }
+
+ /**
+ * Adds a component to the distinguished name.
+ *
+ * @param string $component
+ * @param string $value
+ *
+ * @throws \UnexpectedValueException When the given name does not exist.
+ */
+ protected function addComponent($component, $value)
+ {
+ $this->validateComponentExists($component);
+
+ // We need to make sure the value we're given isn't empty before adding it into our components.
+ if (!empty($value)) {
+ $this->components[$component][] = $value;
+ }
+ }
+
+ /**
+ * Removes the given value from the given component.
+ *
+ * @param string $component
+ * @param string $value
+ *
+ * @throws \UnexpectedValueException When the given component does not exist.
+ *
+ * @return void
+ */
+ protected function removeComponent($component, $value)
+ {
+ $this->validateComponentExists($component);
+
+ $this->components[$component] = array_diff($this->components[$component], [$value]);
+ }
+
+ /**
+ * Validates that the given component exists in the available components.
+ *
+ * @param string $component The name of the component to validate.
+ *
+ * @throws \UnexpectedValueException When the given component does not exist.
+ *
+ * @return void
+ */
+ protected function validateComponentExists($component)
+ {
+ if (!array_key_exists($component, $this->components)) {
+ throw new \UnexpectedValueException("The RDN component '$component' does not exist.");
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/Guid.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/Guid.php
new file mode 100644
index 0000000..6c6a600
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/Guid.php
@@ -0,0 +1,157 @@
+<?php
+
+namespace Adldap\Models\Attributes;
+
+use Adldap\Utilities;
+use InvalidArgumentException;
+
+class Guid
+{
+ /**
+ * The string GUID value.
+ *
+ * @var string
+ */
+ protected $value;
+
+ /**
+ * The guid structure in order by section to parse using substr().
+ *
+ * @author Chad Sikorra <Chad.Sikorra@gmail.com>
+ *
+ * @link https://github.com/ldaptools/ldaptools
+ *
+ * @var array
+ */
+ protected $guidSections = [
+ [[-26, 2], [-28, 2], [-30, 2], [-32, 2]],
+ [[-22, 2], [-24, 2]],
+ [[-18, 2], [-20, 2]],
+ [[-16, 4]],
+ [[-12, 12]],
+ ];
+
+ /**
+ * The hexadecimal octet order based on string position.
+ *
+ * @author Chad Sikorra <Chad.Sikorra@gmail.com>
+ *
+ * @link https://github.com/ldaptools/ldaptools
+ *
+ * @var array
+ */
+ protected $octetSections = [
+ [6, 4, 2, 0],
+ [10, 8],
+ [14, 12],
+ [16, 18, 20, 22, 24, 26, 28, 30],
+ ];
+
+ /**
+ * Determines if the specified GUID is valid.
+ *
+ * @param string $guid
+ *
+ * @return bool
+ */
+ public static function isValid($guid)
+ {
+ return Utilities::isValidGuid($guid);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param mixed $value
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct($value)
+ {
+ if (static::isValid($value)) {
+ $this->value = $value;
+ } elseif ($value = $this->binaryGuidToString($value)) {
+ $this->value = $value;
+ } else {
+ throw new InvalidArgumentException('Invalid Binary / String GUID.');
+ }
+ }
+
+ /**
+ * Returns the string value of the GUID.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Returns the string value of the SID.
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Get the binary representation of the GUID string.
+ *
+ * @return string
+ */
+ public function getBinary()
+ {
+ $data = '';
+
+ $guid = str_replace('-', '', $this->value);
+
+ foreach ($this->octetSections as $section) {
+ $data .= $this->parseSection($guid, $section, true);
+ }
+
+ return hex2bin($data);
+ }
+
+ /**
+ * Returns the string variant of a binary GUID.
+ *
+ * @param string $binary
+ *
+ * @return string|null
+ */
+ protected function binaryGuidToString($binary)
+ {
+ return Utilities::binaryGuidToString($binary);
+ }
+
+ /**
+ * Return the specified section of the hexadecimal string.
+ *
+ * @author Chad Sikorra <Chad.Sikorra@gmail.com>
+ *
+ * @link https://github.com/ldaptools/ldaptools
+ *
+ * @param string $hex The full hex string.
+ * @param array $sections An array of start and length (unless octet is true, then length is always 2).
+ * @param bool $octet Whether this is for octet string form.
+ *
+ * @return string The concatenated sections in upper-case.
+ */
+ protected function parseSection($hex, array $sections, $octet = false)
+ {
+ $parsedString = '';
+
+ foreach ($sections as $section) {
+ $start = $octet ? $section : $section[0];
+
+ $length = $octet ? 2 : $section[1];
+
+ $parsedString .= substr($hex, $start, $length);
+ }
+
+ return $parsedString;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/MbString.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/MbString.php
new file mode 100644
index 0000000..54a0db8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/MbString.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace Adldap\Models\Attributes;
+
+class MbString
+{
+ /**
+ * Get the integer value of a specific character.
+ *
+ * @param $string
+ *
+ * @return int
+ */
+ public static function ord($string)
+ {
+ if (self::isLoaded()) {
+ $result = unpack('N', mb_convert_encoding($string, 'UCS-4BE', 'UTF-8'));
+
+ if (is_array($result) === true) {
+ return $result[1];
+ }
+ }
+
+ return ord($string);
+ }
+
+ /**
+ * Get the character for a specific integer value.
+ *
+ * @param $int
+ *
+ * @return string
+ */
+ public static function chr($int)
+ {
+ if (self::isLoaded()) {
+ return mb_convert_encoding(pack('n', $int), 'UTF-8', 'UTF-16BE');
+ }
+
+ return chr($int);
+ }
+
+ /**
+ * Split a string into its individual characters and return it as an array.
+ *
+ * @param string $value
+ *
+ * @return string[]
+ */
+ public static function split($value)
+ {
+ return preg_split('/(?<!^)(?!$)/u', $value);
+ }
+
+ /**
+ * Detects if the given string is UTF 8.
+ *
+ * @param $string
+ *
+ * @return string|false
+ */
+ public static function isUtf8($string)
+ {
+ if (self::isLoaded()) {
+ return mb_detect_encoding($string, 'UTF-8', $strict = true);
+ }
+
+ return $string;
+ }
+
+ /**
+ * Checks if the mbstring extension is enabled in PHP.
+ *
+ * @return bool
+ */
+ public static function isLoaded()
+ {
+ return extension_loaded('mbstring');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/Sid.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/Sid.php
new file mode 100644
index 0000000..a599e2c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/Sid.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace Adldap\Models\Attributes;
+
+use Adldap\Utilities;
+use InvalidArgumentException;
+
+class Sid
+{
+ /**
+ * The string SID value.
+ *
+ * @var string
+ */
+ protected $value;
+
+ /**
+ * Determines if the specified SID is valid.
+ *
+ * @param string $sid
+ *
+ * @return bool
+ */
+ public static function isValid($sid)
+ {
+ return Utilities::isValidSid($sid);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param mixed $value
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct($value)
+ {
+ if (static::isValid($value)) {
+ $this->value = $value;
+ } elseif ($value = $this->binarySidToString($value)) {
+ $this->value = $value;
+ } else {
+ throw new InvalidArgumentException('Invalid Binary / String SID.');
+ }
+ }
+
+ /**
+ * Returns the string value of the SID.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Returns the string value of the SID.
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Returns the binary variant of the SID.
+ *
+ * @return string
+ */
+ public function getBinary()
+ {
+ $sid = explode('-', ltrim($this->value, 'S-'));
+
+ $level = (int) array_shift($sid);
+
+ $authority = (int) array_shift($sid);
+
+ $subAuthorities = array_map('intval', $sid);
+
+ $params = array_merge(
+ ['C2xxNV*', $level, count($subAuthorities), $authority],
+ $subAuthorities
+ );
+
+ return call_user_func_array('pack', $params);
+ }
+
+ /**
+ * Returns the string variant of a binary SID.
+ *
+ * @param string $binary
+ *
+ * @return string|null
+ */
+ protected function binarySidToString($binary)
+ {
+ return Utilities::binarySidToString($binary);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/TSProperty.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/TSProperty.php
new file mode 100644
index 0000000..aa3d63c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/TSProperty.php
@@ -0,0 +1,396 @@
+<?php
+
+namespace Adldap\Models\Attributes;
+
+class TSProperty
+{
+ /**
+ * Nibble control values. The first value for each is if the nibble is <= 9, otherwise the second value is used.
+ */
+ const NIBBLE_CONTROL = [
+ 'X' => ['001011', '011010'],
+ 'Y' => ['001110', '011010'],
+ ];
+
+ /**
+ * The nibble header.
+ */
+ const NIBBLE_HEADER = '1110';
+
+ /**
+ * Conversion factor needed for time values in the TSPropertyArray (stored in microseconds).
+ */
+ const TIME_CONVERSION = 60 * 1000;
+
+ /**
+ * A simple map to help determine how the property needs to be decoded/encoded from/to its binary value.
+ *
+ * There are some names that are simple repeats but have 'W' at the end. Not sure as to what that signifies. I
+ * cannot find any information on them in Microsoft documentation. However, their values appear to stay in sync with
+ * their non 'W' counterparts. But not doing so when manipulating the data manually does not seem to affect anything.
+ * This probably needs more investigation.
+ *
+ * @var array
+ */
+ protected $propTypes = [
+ 'string' => [
+ 'CtxWFHomeDir',
+ 'CtxWFHomeDirW',
+ 'CtxWFHomeDirDrive',
+ 'CtxWFHomeDirDriveW',
+ 'CtxInitialProgram',
+ 'CtxInitialProgramW',
+ 'CtxWFProfilePath',
+ 'CtxWFProfilePathW',
+ 'CtxWorkDirectory',
+ 'CtxWorkDirectoryW',
+ 'CtxCallbackNumber',
+ ],
+ 'time' => [
+ 'CtxMaxDisconnectionTime',
+ 'CtxMaxConnectionTime',
+ 'CtxMaxIdleTime',
+ ],
+ 'int' => [
+ 'CtxCfgFlags1',
+ 'CtxCfgPresent',
+ 'CtxKeyboardLayout',
+ 'CtxMinEncryptionLevel',
+ 'CtxNWLogonServer',
+ 'CtxShadow',
+ ],
+ ];
+
+ /**
+ * The property name.
+ *
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * The property value.
+ *
+ * @var string|int
+ */
+ protected $value;
+
+ /**
+ * The property value type.
+ *
+ * @var int
+ */
+ protected $valueType = 1;
+
+ /**
+ * Pass binary TSProperty data to construct its object representation.
+ *
+ * @param string|null $value
+ */
+ public function __construct($value = null)
+ {
+ if ($value) {
+ $this->decode(bin2hex($value));
+ }
+ }
+
+ /**
+ * Set the name for the TSProperty.
+ *
+ * @param string $name
+ *
+ * @return TSProperty
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * Get the name for the TSProperty.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Set the value for the TSProperty.
+ *
+ * @param string|int $value
+ *
+ * @return TSProperty
+ */
+ public function setValue($value)
+ {
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * Get the value for the TSProperty.
+ *
+ * @return string|int
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Convert the TSProperty name/value back to its binary
+ * representation for the userParameters blob.
+ *
+ * @return string
+ */
+ public function toBinary()
+ {
+ $name = bin2hex($this->name);
+
+ $binValue = $this->getEncodedValueForProp($this->name, $this->value);
+
+ $valueLen = strlen(bin2hex($binValue)) / 3;
+
+ $binary = hex2bin(
+ $this->dec2hex(strlen($name))
+ .$this->dec2hex($valueLen)
+ .$this->dec2hex($this->valueType)
+ .$name
+ );
+
+ return $binary.$binValue;
+ }
+
+ /**
+ * Given a TSProperty blob, decode the name/value/type/etc.
+ *
+ * @param string $tsProperty
+ */
+ protected function decode($tsProperty)
+ {
+ $nameLength = hexdec(substr($tsProperty, 0, 2));
+
+ // 1 data byte is 3 encoded bytes
+ $valueLength = hexdec(substr($tsProperty, 2, 2)) * 3;
+
+ $this->valueType = hexdec(substr($tsProperty, 4, 2));
+ $this->name = pack('H*', substr($tsProperty, 6, $nameLength));
+ $this->value = $this->getDecodedValueForProp($this->name, substr($tsProperty, 6 + $nameLength, $valueLength));
+ }
+
+ /**
+ * Based on the property name/value in question, get its encoded form.
+ *
+ * @param string $propName
+ * @param string|int $propValue
+ *
+ * @return string
+ */
+ protected function getEncodedValueForProp($propName, $propValue)
+ {
+ if (in_array($propName, $this->propTypes['string'])) {
+ // Simple strings are null terminated. Unsure if this is
+ // needed or simply a product of how ADUC does stuff?
+ $value = $this->encodePropValue($propValue."\0", true);
+ } elseif (in_array($propName, $this->propTypes['time'])) {
+ // Needs to be in microseconds (assuming it is in minute format)...
+ $value = $this->encodePropValue($propValue * self::TIME_CONVERSION);
+ } else {
+ $value = $this->encodePropValue($propValue);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Based on the property name in question, get its actual value from the binary blob value.
+ *
+ * @param string $propName
+ * @param string $propValue
+ *
+ * @return string|int
+ */
+ protected function getDecodedValueForProp($propName, $propValue)
+ {
+ if (in_array($propName, $this->propTypes['string'])) {
+ // Strip away null terminators. I think this should
+ // be desired, otherwise it just ends in confusion.
+ $value = str_replace("\0", '', $this->decodePropValue($propValue, true));
+ } elseif (in_array($propName, $this->propTypes['time'])) {
+ // Convert from microseconds to minutes (how ADUC displays
+ // it anyway, and seems the most practical).
+ $value = hexdec($this->decodePropValue($propValue)) / self::TIME_CONVERSION;
+ } elseif (in_array($propName, $this->propTypes['int'])) {
+ $value = hexdec($this->decodePropValue($propValue));
+ } else {
+ $value = $this->decodePropValue($propValue);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Decode the property by inspecting the nibbles of each blob, checking
+ * the control, and adding up the results into a final value.
+ *
+ * @param string $hex
+ * @param bool $string Whether or not this is simple string data.
+ *
+ * @return string
+ */
+ protected function decodePropValue($hex, $string = false)
+ {
+ $decodePropValue = '';
+
+ $blobs = str_split($hex, 6);
+
+ foreach ($blobs as $blob) {
+ $bin = decbin(hexdec($blob));
+
+ $controlY = substr($bin, 4, 6);
+ $nibbleY = substr($bin, 10, 4);
+ $controlX = substr($bin, 14, 6);
+ $nibbleX = substr($bin, 20, 4);
+
+ $byte = $this->nibbleControl($nibbleX, $controlX).$this->nibbleControl($nibbleY, $controlY);
+
+ if ($string) {
+ $decodePropValue .= MbString::chr(bindec($byte));
+ } else {
+ $decodePropValue = $this->dec2hex(bindec($byte)).$decodePropValue;
+ }
+ }
+
+ return $decodePropValue;
+ }
+
+ /**
+ * Get the encoded property value as a binary blob.
+ *
+ * @param string $value
+ * @param bool $string
+ *
+ * @return string
+ */
+ protected function encodePropValue($value, $string = false)
+ {
+ // An int must be properly padded. (then split and reversed).
+ // For a string, we just split the chars. This seems
+ // to be the easiest way to handle UTF-8 characters
+ // instead of trying to work with their hex values.
+ $chars = $string ? MbString::split($value) : array_reverse(str_split($this->dec2hex($value, 8), 2));
+
+ $encoded = '';
+
+ foreach ($chars as $char) {
+ // Get the bits for the char. Using this method to ensure it is fully padded.
+ $bits = sprintf('%08b', $string ? MbString::ord($char) : hexdec($char));
+ $nibbleX = substr($bits, 0, 4);
+ $nibbleY = substr($bits, 4, 4);
+
+ // Construct the value with the header, high nibble, then low nibble.
+ $value = self::NIBBLE_HEADER;
+
+ foreach (['Y' => $nibbleY, 'X' => $nibbleX] as $nibbleType => $nibble) {
+ $value .= $this->getNibbleWithControl($nibbleType, $nibble);
+ }
+
+ // Convert it back to a binary bit stream
+ foreach ([0, 8, 16] as $start) {
+ $encoded .= $this->packBitString(substr($value, $start, 8), 8);
+ }
+ }
+
+ return $encoded;
+ }
+
+ /**
+ * PHP's pack() function has no 'b' or 'B' template. This is
+ * a workaround that turns a literal bit-string into a
+ * packed byte-string with 8 bits per byte.
+ *
+ * @param string $bits
+ * @param bool $len
+ *
+ * @return string
+ */
+ protected function packBitString($bits, $len)
+ {
+ $bits = substr($bits, 0, $len);
+ // Pad input with zeros to next multiple of 4 above $len
+ $bits = str_pad($bits, 4 * (int) (($len + 3) / 4), '0');
+
+ // Split input into chunks of 4 bits, convert each to hex and pack them
+ $nibbles = str_split($bits, 4);
+ foreach ($nibbles as $i => $nibble) {
+ $nibbles[$i] = base_convert($nibble, 2, 16);
+ }
+
+ return pack('H*', implode('', $nibbles));
+ }
+
+ /**
+ * Based on the control, adjust the nibble accordingly.
+ *
+ * @param string $nibble
+ * @param string $control
+ *
+ * @return string
+ */
+ protected function nibbleControl($nibble, $control)
+ {
+ // This control stays constant for the low/high nibbles,
+ // so it doesn't matter which we compare to
+ if ($control == self::NIBBLE_CONTROL['X'][1]) {
+ $dec = bindec($nibble);
+ $dec += 9;
+ $nibble = str_pad(decbin($dec), 4, '0', STR_PAD_LEFT);
+ }
+
+ return $nibble;
+ }
+
+ /**
+ * Get the nibble value with the control prefixed.
+ *
+ * If the nibble dec is <= 9, the control X equals 001011 and Y equals 001110, otherwise if the nibble dec is > 9
+ * the control for X or Y equals 011010. Additionally, if the dec value of the nibble is > 9, then the nibble value
+ * must be subtracted by 9 before the final value is constructed.
+ *
+ * @param string $nibbleType Either X or Y
+ * @param string $nibble
+ *
+ * @return string
+ */
+ protected function getNibbleWithControl($nibbleType, $nibble)
+ {
+ $dec = bindec($nibble);
+
+ if ($dec > 9) {
+ $dec -= 9;
+ $control = self::NIBBLE_CONTROL[$nibbleType][1];
+ } else {
+ $control = self::NIBBLE_CONTROL[$nibbleType][0];
+ }
+
+ return $control.sprintf('%04d', decbin($dec));
+ }
+
+ /**
+ * Need to make sure hex values are always an even length, so pad as needed.
+ *
+ * @param int $int
+ * @param int $padLength The hex string must be padded to this length (with zeros).
+ *
+ * @return string
+ */
+ protected function dec2hex($int, $padLength = 2)
+ {
+ return str_pad(dechex($int), $padLength, 0, STR_PAD_LEFT);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/TSPropertyArray.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/TSPropertyArray.php
new file mode 100644
index 0000000..4eac74b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Attributes/TSPropertyArray.php
@@ -0,0 +1,295 @@
+<?php
+
+namespace Adldap\Models\Attributes;
+
+use InvalidArgumentException;
+
+class TSPropertyArray
+{
+ /**
+ * Represents that the TSPropertyArray data is valid.
+ */
+ const VALID_SIGNATURE = 'P';
+
+ /**
+ * The default values for the TSPropertyArray structure.
+ *
+ * @var array
+ */
+ const DEFAULTS = [
+ 'CtxCfgPresent' => 2953518677,
+ 'CtxWFProfilePath' => '',
+ 'CtxWFProfilePathW' => '',
+ 'CtxWFHomeDir' => '',
+ 'CtxWFHomeDirW' => '',
+ 'CtxWFHomeDirDrive' => '',
+ 'CtxWFHomeDirDriveW' => '',
+ 'CtxShadow' => 1,
+ 'CtxMaxDisconnectionTime' => 0,
+ 'CtxMaxConnectionTime' => 0,
+ 'CtxMaxIdleTime' => 0,
+ 'CtxWorkDirectory' => '',
+ 'CtxWorkDirectoryW' => '',
+ 'CtxCfgFlags1' => 2418077696,
+ 'CtxInitialProgram' => '',
+ 'CtxInitialProgramW' => '',
+ ];
+
+ /**
+ * @var string The default data that occurs before the TSPropertyArray (CtxCfgPresent with a bunch of spaces...?)
+ */
+ protected $defaultPreBinary = '43747843666750726573656e742020202020202020202020202020202020202020202020202020202020202020202020';
+
+ /**
+ * @var TSProperty[]
+ */
+ protected $tsProperty = [];
+
+ /**
+ * @var string
+ */
+ protected $signature = self::VALID_SIGNATURE;
+
+ /**
+ * Binary data that occurs before the TSPropertyArray data in userParameters.
+ *
+ * @var string
+ */
+ protected $preBinary = '';
+
+ /**
+ * Binary data that occurs after the TSPropertyArray data in userParameters.
+ *
+ * @var string
+ */
+ protected $postBinary = '';
+
+ /**
+ * Construct in one of the following ways:.
+ *
+ * - Pass an array of TSProperty key => value pairs (See DEFAULTS constant).
+ * - Pass the userParameters binary value. The object representation of that will be decoded and constructed.
+ * - Pass nothing and a default set of TSProperty key => value pairs will be used (See DEFAULTS constant).
+ *
+ * @param mixed $tsPropertyArray
+ */
+ public function __construct($tsPropertyArray = null)
+ {
+ $this->preBinary = hex2bin($this->defaultPreBinary);
+
+ if (is_null($tsPropertyArray) || is_array($tsPropertyArray)) {
+ $tsPropertyArray = $tsPropertyArray ?: self::DEFAULTS;
+
+ foreach ($tsPropertyArray as $key => $value) {
+ $tsProperty = new TSProperty();
+
+ $this->tsProperty[$key] = $tsProperty->setName($key)->setValue($value);
+ }
+ } else {
+ $this->decodeUserParameters($tsPropertyArray);
+ }
+ }
+
+ /**
+ * Check if a specific TSProperty exists by its property name.
+ *
+ * @param string $propName
+ *
+ * @return bool
+ */
+ public function has($propName)
+ {
+ return array_key_exists(strtolower($propName), array_change_key_case($this->tsProperty));
+ }
+
+ /**
+ * Get a TSProperty object by its property name (ie. CtxWFProfilePath).
+ *
+ * @param string $propName
+ *
+ * @return TSProperty
+ */
+ public function get($propName)
+ {
+ $this->validateProp($propName);
+
+ return $this->getTsPropObj($propName);
+ }
+
+ /**
+ * Add a TSProperty object. If it already exists, it will be overwritten.
+ *
+ * @param TSProperty $tsProperty
+ *
+ * @return $this
+ */
+ public function add(TSProperty $tsProperty)
+ {
+ $this->tsProperty[$tsProperty->getName()] = $tsProperty;
+
+ return $this;
+ }
+
+ /**
+ * Remove a TSProperty by its property name (ie. CtxMinEncryptionLevel).
+ *
+ * @param string $propName
+ *
+ * @return $this
+ */
+ public function remove($propName)
+ {
+ foreach (array_keys($this->tsProperty) as $property) {
+ if (strtolower($propName) == strtolower($property)) {
+ unset($this->tsProperty[$property]);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the value for a specific TSProperty by its name.
+ *
+ * @param string $propName
+ * @param mixed $propValue
+ *
+ * @return $this
+ */
+ public function set($propName, $propValue)
+ {
+ $this->validateProp($propName);
+
+ $this->getTsPropObj($propName)->setValue($propValue);
+
+ return $this;
+ }
+
+ /**
+ * Get the full binary representation of the userParameters containing the TSPropertyArray data.
+ *
+ * @return string
+ */
+ public function toBinary()
+ {
+ $binary = $this->preBinary;
+
+ $binary .= hex2bin(str_pad(dechex(MbString::ord($this->signature)), 2, 0, STR_PAD_LEFT));
+
+ $binary .= hex2bin(str_pad(dechex(count($this->tsProperty)), 2, 0, STR_PAD_LEFT));
+
+ foreach ($this->tsProperty as $tsProperty) {
+ $binary .= $tsProperty->toBinary();
+ }
+
+ return $binary.$this->postBinary;
+ }
+
+ /**
+ * Get a simple associative array containing of all TSProperty names and values.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $userParameters = [];
+
+ foreach ($this->tsProperty as $property => $tsPropObj) {
+ $userParameters[$property] = $tsPropObj->getValue();
+ }
+
+ return $userParameters;
+ }
+
+ /**
+ * Get all TSProperty objects.
+ *
+ * @return TSProperty[]
+ */
+ public function getTSProperties()
+ {
+ return $this->tsProperty;
+ }
+
+ /**
+ * Validates that the given property name exists.
+ *
+ * @param string $propName
+ */
+ protected function validateProp($propName)
+ {
+ if (!$this->has($propName)) {
+ throw new InvalidArgumentException(sprintf('TSProperty for "%s" does not exist.', $propName));
+ }
+ }
+
+ /**
+ * @param string $propName
+ *
+ * @return TSProperty
+ */
+ protected function getTsPropObj($propName)
+ {
+ return array_change_key_case($this->tsProperty)[strtolower($propName)];
+ }
+
+ /**
+ * Get an associative array with all of the userParameters property names and values.
+ *
+ * @param string $userParameters
+ *
+ * @return void
+ */
+ protected function decodeUserParameters($userParameters)
+ {
+ $userParameters = bin2hex($userParameters);
+
+ // Save the 96-byte array of reserved data, so as to not ruin anything that may be stored there.
+ $this->preBinary = hex2bin(substr($userParameters, 0, 96));
+ // The signature is a 2-byte unicode character at the front
+ $this->signature = MbString::chr(hexdec(substr($userParameters, 96, 2)));
+ // This asserts the validity of the tsPropertyArray data. For some reason 'P' means valid...
+ if ($this->signature != self::VALID_SIGNATURE) {
+ throw new InvalidArgumentException('Invalid TSPropertyArray data');
+ }
+
+ // The property count is a 2-byte unsigned integer indicating the number of elements for the tsPropertyArray
+ // It starts at position 98. The actual variable data begins at position 100.
+ $length = $this->addTSPropData(substr($userParameters, 100), hexdec(substr($userParameters, 98, 2)));
+
+ // Reserved data length + (count and sig length == 4) + the added lengths of the TSPropertyArray
+ // This saves anything after that variable TSPropertyArray data, so as to not squash anything stored there
+ if (strlen($userParameters) > (96 + 4 + $length)) {
+ $this->postBinary = hex2bin(substr($userParameters, (96 + 4 + $length)));
+ }
+ }
+
+ /**
+ * Given the start of TSPropertyArray hex data, and the count for the number
+ * of TSProperty structures in contains, parse and split out the
+ * individual TSProperty structures. Return the full length
+ * of the TSPropertyArray data.
+ *
+ * @param string $tsPropertyArray
+ * @param int $tsPropCount
+ *
+ * @return int The length of the data in the TSPropertyArray
+ */
+ protected function addTSPropData($tsPropertyArray, $tsPropCount)
+ {
+ $length = 0;
+
+ for ($i = 0; $i < $tsPropCount; $i++) {
+ // Prop length = name length + value length + type length + the space for the length data.
+ $propLength = hexdec(substr($tsPropertyArray, $length, 2)) + (hexdec(substr($tsPropertyArray, $length + 2, 2)) * 3) + 6;
+
+ $tsProperty = new TSProperty(hex2bin(substr($tsPropertyArray, $length, $propLength)));
+
+ $this->tsProperty[$tsProperty->getName()] = $tsProperty;
+
+ $length += $propLength;
+ }
+
+ return $length;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/BatchModification.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/BatchModification.php
new file mode 100644
index 0000000..08ddca8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/BatchModification.php
@@ -0,0 +1,270 @@
+<?php
+
+namespace Adldap\Models;
+
+use InvalidArgumentException;
+
+/**
+ * Class BatchModification.
+ *
+ * A utility class to assist in the creation of LDAP
+ * batch modifications and ensure their validity.
+ */
+class BatchModification
+{
+ /**
+ * The array keys to be used in batch modifications.
+ */
+ const KEY_ATTRIB = 'attrib';
+ const KEY_MODTYPE = 'modtype';
+ const KEY_VALUES = 'values';
+
+ /**
+ * The original value of the attribute before modification.
+ *
+ * @var null
+ */
+ protected $original = null;
+
+ /**
+ * The attribute of the modification.
+ *
+ * @var int|string
+ */
+ protected $attribute;
+
+ /**
+ * The values of the modification.
+ *
+ * @var array
+ */
+ protected $values = [];
+
+ /**
+ * The modtype integer of the batch modification.
+ *
+ * @var int
+ */
+ protected $type;
+
+ /**
+ * Constructor.
+ *
+ * @param string|null $attribute
+ * @param string|int|null $type
+ * @param array $values
+ */
+ public function __construct($attribute = null, $type = null, $values = [])
+ {
+ $this->setAttribute($attribute)
+ ->setType($type)
+ ->setValues($values);
+ }
+
+ /**
+ * Sets the original value of the attribute before modification.
+ *
+ * @param mixed $original
+ *
+ * @return $this
+ */
+ public function setOriginal($original = null)
+ {
+ $this->original = $original;
+
+ return $this;
+ }
+
+ /**
+ * Returns the original value of the attribute before modification.
+ *
+ * @return mixed
+ */
+ public function getOriginal()
+ {
+ return $this->original;
+ }
+
+ /**
+ * Sets the attribute of the modification.
+ *
+ * @param string $attribute
+ *
+ * @return $this
+ */
+ public function setAttribute($attribute)
+ {
+ $this->attribute = $attribute;
+
+ return $this;
+ }
+
+ /**
+ * Returns the attribute of the modification.
+ *
+ * @return string
+ */
+ public function getAttribute()
+ {
+ return $this->attribute;
+ }
+
+ /**
+ * Sets the values of the modification.
+ *
+ * @param array $values
+ *
+ * @return $this
+ */
+ public function setValues(array $values = [])
+ {
+ $this->values = array_map(function ($value) {
+ // We need to make sure all values given to a batch modification are
+ // strings, otherwise we'll receive an LDAP exception when
+ // we try to process the modification.
+ return (string) $value;
+ }, $values);
+
+ return $this;
+ }
+
+ /**
+ * Returns the values of the modification.
+ *
+ * @return array
+ */
+ public function getValues()
+ {
+ return $this->values;
+ }
+
+ /**
+ * Sets the type of the modification.
+ *
+ * @param int|null $type
+ *
+ * @return $this
+ */
+ public function setType($type = null)
+ {
+ if (!is_null($type) && !$this->isValidType($type)) {
+ throw new InvalidArgumentException('Given batch modification type is invalid.');
+ }
+
+ $this->type = $type;
+
+ return $this;
+ }
+
+ /**
+ * Returns the type of the modification.
+ *
+ * @return int
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Determines if the batch modification
+ * is valid in its current state.
+ *
+ * @return bool
+ */
+ public function isValid()
+ {
+ return !is_null($this->get());
+ }
+
+ /**
+ * Builds the type of modification automatically
+ * based on the current and original values.
+ *
+ * @return $this
+ */
+ public function build()
+ {
+ $filtered = array_diff(
+ array_map('trim', $this->values),
+ ['']
+ );
+
+ if (is_null($this->original)) {
+ // If the original value is null, we'll assume
+ // that the attribute doesn't exist yet.
+ if (!empty($filtered)) {
+ // If the filtered array is not empty, we can
+ // assume we're looking to add values
+ // to the current attribute.
+ $this->setType(LDAP_MODIFY_BATCH_ADD);
+ }
+
+ // If the filtered array is empty and there is no original
+ // value, then we can ignore this attribute since
+ // we can't push null values to the server.
+ } else {
+ if (empty($filtered)) {
+ // If there's an original value and the array is
+ // empty then we can assume we are looking
+ // to completely remove all values
+ // of the current attribute.
+ $this->setType(LDAP_MODIFY_BATCH_REMOVE_ALL);
+ } else {
+ // If the array isn't empty then we can assume
+ // we're looking to replace all attributes.
+ $this->setType(LDAP_MODIFY_BATCH_REPLACE);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the built batch modification array.
+ *
+ * @return array|null
+ */
+ public function get()
+ {
+ switch ($this->type) {
+ case LDAP_MODIFY_BATCH_REMOVE_ALL:
+ // A values key cannot be provided when
+ // a remove all type is selected.
+ return [
+ static::KEY_ATTRIB => $this->attribute,
+ static::KEY_MODTYPE => $this->type,
+ ];
+ case LDAP_MODIFY_BATCH_REMOVE:
+ // Fallthrough.
+ case LDAP_MODIFY_BATCH_ADD:
+ // Fallthrough.
+ case LDAP_MODIFY_BATCH_REPLACE:
+ return [
+ static::KEY_ATTRIB => $this->attribute,
+ static::KEY_MODTYPE => $this->type,
+ static::KEY_VALUES => $this->values,
+ ];
+ default:
+ // If the modtype isn't recognized, we'll return null.
+ return;
+ }
+ }
+
+ /**
+ * Determines if the given modtype is valid.
+ *
+ * @param int $type
+ *
+ * @return bool
+ */
+ protected function isValidType($type)
+ {
+ return in_array($type, [
+ LDAP_MODIFY_BATCH_REMOVE_ALL,
+ LDAP_MODIFY_BATCH_REMOVE,
+ LDAP_MODIFY_BATCH_REPLACE,
+ LDAP_MODIFY_BATCH_ADD,
+ ]);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Computer.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Computer.php
new file mode 100644
index 0000000..e00f259
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Computer.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace Adldap\Models;
+
+/**
+ * Class Computer.
+ *
+ * Represents an LDAP computer / server.
+ */
+class Computer extends Entry
+{
+ use Concerns\HasMemberOf;
+ use Concerns\HasDescription;
+ use Concerns\HasLastLogonAndLogOff;
+ use Concerns\HasUserAccountControl;
+ use Concerns\HasCriticalSystemObject;
+
+ /**
+ * Returns the computers operating system.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679076(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getOperatingSystem()
+ {
+ return $this->getFirstAttribute($this->schema->operatingSystem());
+ }
+
+ /**
+ * Returns the computers operating system version.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679079(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getOperatingSystemVersion()
+ {
+ return $this->getFirstAttribute($this->schema->operatingSystemVersion());
+ }
+
+ /**
+ * Returns the computers operating system service pack.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679078(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getOperatingSystemServicePack()
+ {
+ return $this->getFirstAttribute($this->schema->operatingSystemServicePack());
+ }
+
+ /**
+ * Returns the computers DNS host name.
+ *
+ * @return string
+ */
+ public function getDnsHostName()
+ {
+ return $this->getFirstAttribute($this->schema->dnsHostName());
+ }
+
+ /**
+ * Returns the computers bad password time.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675243(v=vs.85).aspx
+ *
+ * @return int
+ */
+ public function getBadPasswordTime()
+ {
+ return $this->getFirstAttribute($this->schema->badPasswordTime());
+ }
+
+ /**
+ * Returns the computers account expiry date.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675098(v=vs.85).aspx
+ *
+ * @return int
+ */
+ public function getAccountExpiry()
+ {
+ return $this->getFirstAttribute($this->schema->accountExpires());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasAttributes.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasAttributes.php
new file mode 100644
index 0000000..2235bbe
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasAttributes.php
@@ -0,0 +1,345 @@
+<?php
+
+namespace Adldap\Models\Concerns;
+
+use Illuminate\Support\Arr;
+
+trait HasAttributes
+{
+ /**
+ * The default output date format for all time related methods.
+ *
+ * Default format is suited for MySQL timestamps.
+ *
+ * @var string
+ */
+ public $dateFormat = 'Y-m-d H:i:s';
+
+ /**
+ * The format that is used to convert timestamps to unix timestamps.
+ *
+ * Currently set for compatibility with Active Directory.
+ *
+ * @var string
+ */
+ protected $timestampFormat = 'YmdHis.0Z';
+
+ /**
+ * The models attributes.
+ *
+ * @var array
+ */
+ protected $attributes = [];
+
+ /**
+ * The models original attributes.
+ *
+ * @var array
+ */
+ protected $original = [];
+
+ /**
+ * Dynamically retrieve attributes on the object.
+ *
+ * @param mixed $key
+ *
+ * @return bool
+ */
+ public function __get($key)
+ {
+ return $this->getAttribute($key);
+ }
+
+ /**
+ * Dynamically set attributes on the object.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function __set($key, $value)
+ {
+ return $this->setAttribute($key, $value);
+ }
+
+ /**
+ * Synchronizes the models original attributes
+ * with the model's current attributes.
+ *
+ * @return $this
+ */
+ public function syncOriginal()
+ {
+ $this->original = $this->attributes;
+
+ return $this;
+ }
+
+ /**
+ * Returns the models attribute with the specified key.
+ *
+ * If a sub-key is specified, it will try and
+ * retrieve it from the parent keys array.
+ *
+ * @param int|string $key
+ * @param int|string $subKey
+ *
+ * @return mixed
+ */
+ public function getAttribute($key, $subKey = null)
+ {
+ if (!$key) {
+ return;
+ }
+
+ // We'll normalize the given key to prevent case sensitivity issues.
+ $key = $this->normalizeAttributeKey($key);
+
+ if (is_null($subKey) && $this->hasAttribute($key)) {
+ return $this->attributes[$key];
+ } elseif ($this->hasAttribute($key, $subKey)) {
+ return $this->attributes[$key][$subKey];
+ }
+ }
+
+ /**
+ * Returns the first attribute by the specified key.
+ *
+ * @param string $key
+ *
+ * @return mixed
+ */
+ public function getFirstAttribute($key)
+ {
+ return $this->getAttribute($key, 0);
+ }
+
+ /**
+ * Returns all of the models attributes.
+ *
+ * @return array
+ */
+ public function getAttributes()
+ {
+ return $this->attributes;
+ }
+
+ /**
+ * Fills the entry with the supplied attributes.
+ *
+ * @param array $attributes
+ *
+ * @return $this
+ */
+ public function fill(array $attributes = [])
+ {
+ foreach ($attributes as $key => $value) {
+ $this->setAttribute($key, $value);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Sets an attributes value by the specified key and sub-key.
+ *
+ * @param int|string $key
+ * @param mixed $value
+ * @param int|string $subKey
+ *
+ * @return $this
+ */
+ public function setAttribute($key, $value, $subKey = null)
+ {
+ // Normalize key.
+ $key = $this->normalizeAttributeKey($key);
+
+ // If the key is equal to 'dn', we'll automatically
+ // change it to the full attribute name.
+ $key = ($key == 'dn' ? $this->schema->distinguishedName() : $key);
+
+ if (is_null($subKey)) {
+ // We need to ensure all attributes are set as arrays so all
+ // of our model methods retrieve attributes correctly.
+ $this->attributes[$key] = is_array($value) ? $value : [$value];
+ } else {
+ $this->attributes[$key][$subKey] = $value;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Sets the first attributes value by the specified key.
+ *
+ * @param int|string $key
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function setFirstAttribute($key, $value)
+ {
+ return $this->setAttribute($key, $value, 0);
+ }
+
+ /**
+ * Sets the attributes property.
+ *
+ * Used when constructing an existing LDAP record.
+ *
+ * @param array $attributes
+ *
+ * @return $this
+ */
+ public function setRawAttributes(array $attributes = [])
+ {
+ // We'll filter out those annoying 'count' keys returned with LDAP results,
+ // and lowercase all root array keys to prevent any casing issues.
+ $this->attributes = array_change_key_case($this->filterRawAttributes($attributes), CASE_LOWER);
+
+ // We'll pull out the distinguished name from our raw attributes
+ // and set it into our attributes array with the full attribute
+ // definition. This allows us to normalize distinguished
+ // names across different LDAP variants.
+ if ($dn = Arr::get($attributes, 'dn')) {
+ // In some LDAP variants, the distinguished
+ // name is returned as an array.
+ if (is_array($dn)) {
+ $dn = Arr::first($dn);
+ }
+
+ $this->setDistinguishedName($dn);
+ }
+
+ $this->syncOriginal();
+
+ // Set exists to true since raw attributes are only
+ // set in the case of attributes being loaded by
+ // query results.
+ $this->exists = true;
+
+ return $this;
+ }
+
+ /**
+ * Filters the count key recursively from raw LDAP attributes.
+ *
+ * @param array $attributes
+ * @param array|string $keys
+ *
+ * @return array
+ */
+ public function filterRawAttributes(array $attributes = [], $keys = ['count', 'dn'])
+ {
+ $attributes = Arr::except($attributes, $keys);
+
+ array_walk($attributes, function (&$value) use ($keys) {
+ $value = is_array($value) ?
+ $this->filterRawAttributes($value, $keys) :
+ $value;
+ });
+
+ return $attributes;
+ }
+
+ /**
+ * Returns true / false if the specified attribute
+ * exists in the attributes array.
+ *
+ * @param int|string $key
+ * @param int|string $subKey
+ *
+ * @return bool
+ */
+ public function hasAttribute($key, $subKey = null)
+ {
+ // Normalize key.
+ $key = $this->normalizeAttributeKey($key);
+
+ if (is_null($subKey)) {
+ return Arr::has($this->attributes, $key);
+ }
+
+ return Arr::has($this->attributes, "$key.$subKey");
+ }
+
+ /**
+ * Returns the number of attributes inside
+ * the attributes property.
+ *
+ * @return int
+ */
+ public function countAttributes()
+ {
+ return count($this->getAttributes());
+ }
+
+ /**
+ * Returns the models original attributes.
+ *
+ * @return array
+ */
+ public function getOriginal()
+ {
+ return $this->original;
+ }
+
+ /**
+ * Get the attributes that have been changed since last sync.
+ *
+ * @return array
+ */
+ public function getDirty()
+ {
+ $dirty = [];
+
+ foreach ($this->attributes as $key => $value) {
+ if (!$this->originalIsEquivalent($key)) {
+ // We need to reset the array's indices using array_values due to
+ // LDAP requiring consecutive indices (0, 1, 2 etc.)
+ $dirty[$key] = array_values($value);
+ }
+ }
+
+ return $dirty;
+ }
+
+ /**
+ * Returns a normalized attribute key.
+ *
+ * @param string $key
+ *
+ * @return string
+ */
+ protected function normalizeAttributeKey($key)
+ {
+ return strtolower($key);
+ }
+
+ /**
+ * Determine if the new and old values for a given key are equivalent.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ protected function originalIsEquivalent($key)
+ {
+ if (!array_key_exists($key, $this->original)) {
+ return false;
+ }
+
+ $current = $this->attributes[$key];
+
+ $original = $this->original[$key];
+
+ if ($current === $original) {
+ return true;
+ }
+
+ return is_numeric($current) &&
+ is_numeric($original) &&
+ strcmp((string) $current, (string) $original) === 0;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasCriticalSystemObject.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasCriticalSystemObject.php
new file mode 100644
index 0000000..e85cac1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasCriticalSystemObject.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Adldap\Models\Concerns;
+
+trait HasCriticalSystemObject
+{
+ /**
+ * Returns true / false if the entry is a critical system object.
+ *
+ * @return null|bool
+ */
+ public function isCriticalSystemObject()
+ {
+ $attribute = $this->getFirstAttribute($this->schema->isCriticalSystemObject());
+
+ return $this->convertStringToBool($attribute);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasDescription.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasDescription.php
new file mode 100644
index 0000000..dfc05ed
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasDescription.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Adldap\Models\Concerns;
+
+trait HasDescription
+{
+ /**
+ * Returns the models's description.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675492(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getDescription()
+ {
+ return $this->getFirstAttribute($this->schema->description());
+ }
+
+ /**
+ * Sets the models's description.
+ *
+ * @param string $description
+ *
+ * @return $this
+ */
+ public function setDescription($description)
+ {
+ return $this->setFirstAttribute($this->schema->description(), $description);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasEvents.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasEvents.php
new file mode 100644
index 0000000..37abb81
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasEvents.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Adldap\Models\Concerns;
+
+use Adldap\Adldap;
+use Adldap\Models\Events\Event;
+
+trait HasEvents
+{
+ /**
+ * Fires the specified model event.
+ *
+ * @param Event $event
+ *
+ * @return mixed
+ */
+ protected function fireModelEvent(Event $event)
+ {
+ return Adldap::getEventDispatcher()->fire($event);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasLastLogonAndLogOff.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasLastLogonAndLogOff.php
new file mode 100644
index 0000000..3aee2a5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasLastLogonAndLogOff.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace Adldap\Models\Concerns;
+
+trait HasLastLogonAndLogOff
+{
+ /**
+ * Returns the models's last log off date.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676822(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getLastLogOff()
+ {
+ return $this->getFirstAttribute($this->schema->lastLogOff());
+ }
+
+ /**
+ * Returns the models's last log on date.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676823(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getLastLogon()
+ {
+ return $this->getFirstAttribute($this->schema->lastLogOn());
+ }
+
+ /**
+ * Returns the models's last log on timestamp.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676824(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getLastLogonTimestamp()
+ {
+ return $this->getFirstAttribute($this->schema->lastLogOnTimestamp());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasMemberOf.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasMemberOf.php
new file mode 100644
index 0000000..3c1b85e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasMemberOf.php
@@ -0,0 +1,260 @@
+<?php
+
+namespace Adldap\Models\Concerns;
+
+use Adldap\Utilities;
+use Adldap\Models\User;
+use Adldap\Models\Group;
+use Adldap\Query\Collection;
+
+trait HasMemberOf
+{
+ /**
+ * Returns an array of distinguished names of groups that the current model belongs to.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms677099(v=vs.85).aspx
+ *
+ * @return array
+ */
+ public function getMemberOf()
+ {
+ $dns = $this->getAttribute($this->schema->memberOf());
+
+ // Normalize returned distinguished names if the attribute is null.
+ return is_array($dns) ? $dns : [];
+ }
+
+ /**
+ * Adds the current model to the specified group.
+ *
+ * @param string|Group $group
+ *
+ * @return bool
+ */
+ public function addGroup($group)
+ {
+ if (is_string($group)) {
+ // If the group is a string, we'll assume the dev is passing
+ // in a DN string of the group. We'll try to locate it.
+ $group = $this->query->newInstance()->findByDn($group);
+ }
+
+ if ($group instanceof Group) {
+ // If the group is Group model instance, we can
+ // add the current models DN to the group.
+ return $group->addMember($this->getDn());
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes the current model from the specified group.
+ *
+ * @param string|Group $group
+ *
+ * @return bool
+ */
+ public function removeGroup($group)
+ {
+ if (is_string($group)) {
+ // If the group is a string, we'll assume the dev is passing
+ // in a DN string of the group. We'll try to locate it.
+ $group = $this->query->newInstance()->findByDn($group);
+ }
+
+ if ($group instanceof Group) {
+ // If the group is Group model instance, we can
+ // remove the current models DN from the group.
+ return $group->removeMember($this->getDn());
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes the current model from all groups.
+ *
+ * @return array The group distinguished names that were successfully removed
+ */
+ public function removeAllGroups()
+ {
+ $removed = [];
+
+ foreach ($this->getMemberOf() as $group) {
+ if ($this->removeGroup($group)) {
+ $removed[] = $group;
+ }
+ }
+
+ return $removed;
+ }
+
+ /**
+ * Returns the models groups that it is apart of.
+ *
+ * If a recursive option is given, groups of groups
+ * are retrieved and then merged with
+ * the resulting collection.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms677099(v=vs.85).aspx
+ *
+ * @param array $fields
+ * @param bool $recursive
+ * @param array $visited
+ *
+ * @return Collection
+ */
+ public function getGroups(array $fields = ['*'], $recursive = false, array $visited = [])
+ {
+ if (!in_array($this->schema->memberOf(), $fields)) {
+ // We want to make sure that we always select the memberof
+ // field in case developers want recursive members.
+ $fields = array_merge($fields, [$this->schema->memberOf()]);
+ }
+
+ $groups = $this->getGroupsByNames($this->getMemberOf(), $fields);
+
+ // We need to check if we're working with a User model. Only users
+ // contain a primary group. If we are, we'll merge the users
+ // primary group into the resulting collection.
+ if ($this instanceof User && $primary = $this->getPrimaryGroup()) {
+ $groups->push($primary);
+ }
+
+ // If recursive results are requested, we'll ask each group
+ // for their groups, and merge the resulting collection.
+ if ($recursive) {
+ /** @var Group $group */
+ foreach ($groups as $group) {
+ // We need to validate that we haven't already queried
+ // for this group's members so we don't allow
+ // infinite recursion in case of circular
+ // group dependencies in LDAP.
+ if (!in_array($group->getDn(), $visited)) {
+ $visited[] = $group->getDn();
+
+ $members = $group->getGroups($fields, $recursive, $visited);
+
+ /** @var Group $member */
+ foreach ($members as $member) {
+ $visited[] = $member->getDn();
+ }
+
+ $groups = $groups->merge($members);
+ }
+ }
+ }
+
+ return $groups;
+ }
+
+ /**
+ * Returns the models groups names in a single dimension array.
+ *
+ * If a recursive option is given, groups of groups
+ * are retrieved and then merged with
+ * the resulting collection.
+ *
+ * @param bool $recursive
+ *
+ * @return array
+ */
+ public function getGroupNames($recursive = false)
+ {
+ $fields = [$this->schema->commonName(), $this->schema->memberOf()];
+
+ $names = $this->getGroups($fields, $recursive)->map(function (Group $group) {
+ return $group->getCommonName();
+ })->toArray();
+
+ return array_unique($names);
+ }
+
+ /**
+ * Determine if the current model is a member of the specified group(s).
+ *
+ * @param mixed $group
+ * @param bool $recursive
+ *
+ * @return bool
+ */
+ public function inGroup($group, $recursive = false)
+ {
+ $memberOf = $this->getGroups(['cn'], $recursive);
+
+ if ($group instanceof Collection) {
+ // If we've been given a collection then we'll convert
+ // it to an array to normalize the value.
+ $group = $group->toArray();
+ }
+
+ $groups = is_array($group) ? $group : [$group];
+
+ foreach ($groups as $group) {
+ // We need to iterate through each given group that the
+ // model must be apart of, then go through the models
+ // actual groups and perform validation.
+ $exists = $memberOf->filter(function (Group $parent) use ($group) {
+ return $this->groupIsParent($group, $parent);
+ })->count() !== 0;
+
+ if (!$exists) {
+ // If the current group isn't at all contained
+ // in the memberOf collection, we'll
+ // return false here.
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Retrieves groups by their distinguished name.
+ *
+ * @param array $dns
+ * @param array $fields
+ *
+ * @return Collection
+ */
+ protected function getGroupsByNames(array $dns = [], $fields = [])
+ {
+ $query = $this->query->newInstance();
+
+ return $query->newCollection($dns)->map(function ($dn) use ($query, $fields) {
+ return $query->select($fields)->clearFilters()->findByDn($dn);
+ })->filter(function ($group) {
+ return $group instanceof Group;
+ });
+ }
+
+ /**
+ * Validates if the specified group is the given parent instance.
+ *
+ * @param Group|string $group
+ * @param Group $parent
+ *
+ * @return bool
+ */
+ protected function groupIsParent($group, Group $parent)
+ {
+ if ($group instanceof Group) {
+ // We've been given a group instance, we'll compare their DNs.
+ return $parent->getDn() === $group->getDn();
+ }
+
+ if (Utilities::explodeDn($group)) {
+ // We've been given a DN, we'll compare it to the parents.
+ return $parent->getDn() === $group;
+ }
+
+ if (!empty($group)) {
+ // We've been given just a string, we'll
+ // compare it to the parents name.
+ return $parent->getCommonName() === $group;
+ }
+
+ return false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasUserAccountControl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasUserAccountControl.php
new file mode 100644
index 0000000..857378b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasUserAccountControl.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Adldap\Models\Concerns;
+
+use Adldap\Models\Attributes\AccountControl;
+
+trait HasUserAccountControl
+{
+ /**
+ * Returns the users user account control integer.
+ *
+ * @return string
+ */
+ public function getUserAccountControl()
+ {
+ return $this->getFirstAttribute($this->schema->userAccountControl());
+ }
+
+ /**
+ * Returns the users user account control as an AccountControl object.
+ *
+ * @return AccountControl
+ */
+ public function getUserAccountControlObject()
+ {
+ return new AccountControl($this->getUserAccountControl());
+ }
+
+ /**
+ * Sets the users account control property.
+ *
+ * @param int|string|AccountControl $accountControl
+ *
+ * @return $this
+ */
+ public function setUserAccountControl($accountControl)
+ {
+ return $this->setAttribute($this->schema->userAccountControl(), (string) $accountControl);
+ }
+
+ /**
+ * Returns if the user is disabled.
+ *
+ * @return bool
+ */
+ public function isDisabled()
+ {
+ return ($this->getUserAccountControl() & AccountControl::ACCOUNTDISABLE) === AccountControl::ACCOUNTDISABLE;
+ }
+
+ /**
+ * Returns if the user is enabled.
+ *
+ * @return bool
+ */
+ public function isEnabled()
+ {
+ return $this->getUserAccountControl() === null ? false : !$this->isDisabled();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasUserProperties.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasUserProperties.php
new file mode 100644
index 0000000..0d1c541
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Concerns/HasUserProperties.php
@@ -0,0 +1,453 @@
+<?php
+
+namespace Adldap\Models\Concerns;
+
+trait HasUserProperties
+{
+ /**
+ * Returns the users country.
+ *
+ * @return string|null
+ */
+ public function getCountry()
+ {
+ return $this->getFirstAttribute($this->schema->country());
+ }
+
+ /**
+ * Sets the users country.
+ *
+ * @param string $country
+ *
+ * @return $this
+ */
+ public function setCountry($country)
+ {
+ return $this->setFirstAttribute($this->schema->country(), $country);
+ }
+
+ /**
+ * Returns the users department.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675490(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getDepartment()
+ {
+ return $this->getFirstAttribute($this->schema->department());
+ }
+
+ /**
+ * Sets the users department.
+ *
+ * @param string $department
+ *
+ * @return $this
+ */
+ public function setDepartment($department)
+ {
+ return $this->setFirstAttribute($this->schema->department(), $department);
+ }
+
+ /**
+ * Returns the users email address.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676855(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getEmail()
+ {
+ return $this->getFirstAttribute($this->schema->email());
+ }
+
+ /**
+ * Sets the users email.
+ *
+ * Keep in mind this will remove all other
+ * email addresses the user currently has.
+ *
+ * @param string $email
+ *
+ * @return $this
+ */
+ public function setEmail($email)
+ {
+ return $this->setFirstAttribute($this->schema->email(), $email);
+ }
+
+ /**
+ * Returns the users facsimile number.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675675(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getFacsimileNumber()
+ {
+ return $this->getFirstAttribute($this->schema->facsimile());
+ }
+
+ /**
+ * Sets the users facsimile number.
+ *
+ * @param string $number
+ *
+ * @return $this
+ */
+ public function setFacsimileNumber($number)
+ {
+ return $this->setFirstAttribute($this->schema->facsimile(), $number);
+ }
+
+ /**
+ * Returns the users first name.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675719(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getFirstName()
+ {
+ return $this->getFirstAttribute($this->schema->firstName());
+ }
+
+ /**
+ * Sets the users first name.
+ *
+ * @param string $firstName
+ *
+ * @return $this
+ */
+ public function setFirstName($firstName)
+ {
+ return $this->setFirstAttribute($this->schema->firstName(), $firstName);
+ }
+
+ /**
+ * Returns the users initials.
+ *
+ * @return string|null
+ */
+ public function getInitials()
+ {
+ return $this->getFirstAttribute($this->schema->initials());
+ }
+
+ /**
+ * Sets the users initials.
+ *
+ * @param string $initials
+ *
+ * @return $this
+ */
+ public function setInitials($initials)
+ {
+ return $this->setFirstAttribute($this->schema->initials(), $initials);
+ }
+
+ /**
+ * Returns the users IP Phone.
+ *
+ * @return string|null
+ */
+ public function getIpPhone()
+ {
+ return $this->getFirstAttribute($this->schema->ipPhone());
+ }
+
+ /**
+ * Sets the users IP phone.
+ *
+ * @param string $ip
+ *
+ * @return $this
+ */
+ public function setIpPhone($ip)
+ {
+ return $this->setFirstAttribute($this->schema->ipPhone(), $ip);
+ }
+
+ /**
+ * Returns the users last name.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679872(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getLastName()
+ {
+ return $this->getFirstAttribute($this->schema->lastName());
+ }
+
+ /**
+ * Sets the users last name.
+ *
+ * @param string $lastName
+ *
+ * @return $this
+ */
+ public function setLastName($lastName)
+ {
+ return $this->setFirstAttribute($this->schema->lastName(), $lastName);
+ }
+
+ /**
+ * Returns the users postal code.
+ *
+ * @return string|null
+ */
+ public function getPostalCode()
+ {
+ return $this->getFirstAttribute($this->schema->postalCode());
+ }
+
+ /**
+ * Sets the users postal code.
+ *
+ * @param string $postalCode
+ *
+ * @return $this
+ */
+ public function setPostalCode($postalCode)
+ {
+ return $this->setFirstAttribute($this->schema->postalCode(), $postalCode);
+ }
+
+ /**
+ * Get the users post office box.
+ *
+ * @return string|null
+ */
+ public function getPostOfficeBox()
+ {
+ return $this->getFirstAttribute($this->schema->postOfficeBox());
+ }
+
+ /**
+ * Sets the users post office box.
+ *
+ * @param string|int $box
+ *
+ * @return $this
+ */
+ public function setPostOfficeBox($box)
+ {
+ return $this->setFirstAttribute($this->schema->postOfficeBox(), $box);
+ }
+
+ /**
+ * Sets the users proxy addresses.
+ *
+ * This will remove all proxy addresses on the user and insert the specified addresses.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679424(v=vs.85).aspx
+ *
+ * @param array $addresses
+ *
+ * @return $this
+ */
+ public function setProxyAddresses(array $addresses = [])
+ {
+ return $this->setAttribute($this->schema->proxyAddresses(), $addresses);
+ }
+
+ /**
+ * Add's a single proxy address to the user.
+ *
+ * @param string $address
+ *
+ * @return $this
+ */
+ public function addProxyAddress($address)
+ {
+ $addresses = $this->getProxyAddresses();
+
+ $addresses[] = $address;
+
+ return $this->setAttribute($this->schema->proxyAddresses(), $addresses);
+ }
+
+ /**
+ * Returns the users proxy addresses.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679424(v=vs.85).aspx
+ *
+ * @return array
+ */
+ public function getProxyAddresses()
+ {
+ return $this->getAttribute($this->schema->proxyAddresses()) ?? [];
+ }
+
+ /**
+ * Returns the users street address.
+ *
+ * @return string|null
+ */
+ public function getStreetAddress()
+ {
+ return $this->getFirstAttribute($this->schema->streetAddress());
+ }
+
+ /**
+ * Sets the users street address.
+ *
+ * @param string $address
+ *
+ * @return $this
+ */
+ public function setStreetAddress($address)
+ {
+ return $this->setFirstAttribute($this->schema->streetAddress(), $address);
+ }
+
+ /**
+ * Returns the users title.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680037(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getTitle()
+ {
+ return $this->getFirstAttribute($this->schema->title());
+ }
+
+ /**
+ * Sets the users title.
+ *
+ * @param string $title
+ *
+ * @return $this
+ */
+ public function setTitle($title)
+ {
+ return $this->setFirstAttribute($this->schema->title(), $title);
+ }
+
+ /**
+ * Returns the users telephone number.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680027(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getTelephoneNumber()
+ {
+ return $this->getFirstAttribute($this->schema->telephone());
+ }
+
+ /**
+ * Sets the users telephone number.
+ *
+ * @param string $number
+ *
+ * @return $this
+ */
+ public function setTelephoneNumber($number)
+ {
+ return $this->setFirstAttribute($this->schema->telephone(), $number);
+ }
+
+ /**
+ * Returns the users primary mobile phone number.
+ *
+ * @return string|null
+ */
+ public function getMobileNumber()
+ {
+ return $this->getFirstAttribute($this->schema->mobile());
+ }
+
+ /**
+ * Sets the users primary mobile phone number.
+ *
+ * @param string $number
+ *
+ * @return $this
+ */
+ public function setMobileNumber($number)
+ {
+ return $this->setFirstAttribute($this->schema->mobile(), $number);
+ }
+
+ /**
+ * Returns the users secondary (other) mobile phone number.
+ *
+ * @return string|null
+ */
+ public function getOtherMobileNumber()
+ {
+ return $this->getFirstAttribute($this->schema->otherMobile());
+ }
+
+ /**
+ * Sets the users secondary (other) mobile phone number.
+ *
+ * @param string $number
+ *
+ * @return $this
+ */
+ public function setOtherMobileNumber($number)
+ {
+ return $this->setFirstAttribute($this->schema->otherMobile(), $number);
+ }
+
+ /**
+ * Returns the users other mailbox attribute.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679091(v=vs.85).aspx
+ *
+ * @return array
+ */
+ public function getOtherMailbox()
+ {
+ return $this->getAttribute($this->schema->otherMailbox());
+ }
+
+ /**
+ * Sets the users other mailboxes.
+ *
+ * @param array $otherMailbox
+ *
+ * @return $this
+ */
+ public function setOtherMailbox($otherMailbox = [])
+ {
+ return $this->setAttribute($this->schema->otherMailbox(), $otherMailbox);
+ }
+
+ /**
+ * Returns the distinguished name of the user who is the user's manager.
+ *
+ * @return string|null
+ */
+ public function getManager()
+ {
+ return $this->getFirstAttribute($this->schema->manager());
+ }
+
+ /**
+ * Sets the distinguished name of the user who is the user's manager.
+ *
+ * @param string $managerDn
+ *
+ * @return $this
+ */
+ public function setManager($managerDn)
+ {
+ return $this->setFirstAttribute($this->schema->manager(), $managerDn);
+ }
+
+ /**
+ * Returns the users mail nickname.
+ *
+ * @return string|null
+ */
+ public function getMailNickname()
+ {
+ return $this->getFirstAttribute($this->schema->emailNickname());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Contact.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Contact.php
new file mode 100644
index 0000000..517a35b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Contact.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Adldap\Models;
+
+/**
+ * Class Contact.
+ *
+ * Represents an LDAP contact.
+ */
+class Contact extends Entry
+{
+ use Concerns\HasMemberOf;
+ use Concerns\HasUserProperties;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Container.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Container.php
new file mode 100644
index 0000000..faaf1a1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Container.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Adldap\Models;
+
+/**
+ * Class Container.
+ *
+ * Represents an LDAP container.
+ */
+class Container extends Entry
+{
+ use Concerns\HasDescription;
+ use Concerns\HasCriticalSystemObject;
+
+ /**
+ * Returns the containers system flags integer.
+ *
+ * An integer value that contains flags that define additional properties of the class.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680022(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getSystemFlags()
+ {
+ return $this->getFirstAttribute($this->schema->systemFlags());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Entry.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Entry.php
new file mode 100644
index 0000000..be6ef1d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Entry.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Adldap\Models;
+
+/**
+ * Class Entry.
+ *
+ * Represents an LDAP record that could not be identified as another type of model.
+ */
+class Entry extends Model
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Created.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Created.php
new file mode 100644
index 0000000..7e98bc1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Created.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Models\Events;
+
+class Created extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Creating.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Creating.php
new file mode 100644
index 0000000..8482da8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Creating.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Models\Events;
+
+class Creating extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Deleted.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Deleted.php
new file mode 100644
index 0000000..6cfd954
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Deleted.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Models\Events;
+
+class Deleted extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Deleting.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Deleting.php
new file mode 100644
index 0000000..2718376
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Deleting.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Models\Events;
+
+class Deleting extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Event.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Event.php
new file mode 100644
index 0000000..821e391
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Event.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Adldap\Models\Events;
+
+use Adldap\Models\Model;
+
+abstract class Event
+{
+ /**
+ * The model that the event is being triggered on.
+ *
+ * @var Model
+ */
+ protected $model;
+
+ /**
+ * Constructor.
+ *
+ * @param Model $model
+ */
+ public function __construct(Model $model)
+ {
+ $this->model = $model;
+ }
+
+ /**
+ * Returns the model that generated the event.
+ *
+ * @return Model
+ */
+ public function getModel()
+ {
+ return $this->model;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Saved.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Saved.php
new file mode 100644
index 0000000..f775e2e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Saved.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Models\Events;
+
+class Saved extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Saving.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Saving.php
new file mode 100644
index 0000000..b187294
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Saving.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Models\Events;
+
+class Saving extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Updated.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Updated.php
new file mode 100644
index 0000000..ce0721f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Updated.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Models\Events;
+
+class Updated extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Updating.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Updating.php
new file mode 100644
index 0000000..4f33e66
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Events/Updating.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Models\Events;
+
+class Updating extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Factory.php
new file mode 100644
index 0000000..92ad91e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Factory.php
@@ -0,0 +1,209 @@
+<?php
+
+namespace Adldap\Models;
+
+use Adldap\Query\Builder;
+use Adldap\Schemas\ActiveDirectory;
+use Adldap\Schemas\SchemaInterface;
+
+/**
+ * Class Factory.
+ *
+ * Creates new LDAP models.
+ */
+class Factory
+{
+ /**
+ * The LDAP query builder.
+ *
+ * @var Builder
+ */
+ protected $query;
+
+ /**
+ * The LDAP schema.
+ *
+ * @var SchemaInterface
+ */
+ protected $schema;
+
+ /**
+ * Constructor.
+ *
+ * @param Builder $builder
+ */
+ public function __construct(Builder $builder)
+ {
+ $this->setQuery($builder)
+ ->setSchema($builder->getSchema());
+ }
+
+ /**
+ * Sets the current query builder.
+ *
+ * @param Builder $builder
+ *
+ * @return $this
+ */
+ public function setQuery(Builder $builder)
+ {
+ $this->query = $builder;
+
+ return $this;
+ }
+
+ /**
+ * Sets the current schema.
+ *
+ * If null is given, a default ActiveDirectory schema is set.
+ *
+ * @param SchemaInterface|null $schema
+ *
+ * @return $this
+ */
+ public function setSchema(SchemaInterface $schema = null)
+ {
+ $this->schema = $schema ?: new ActiveDirectory();
+
+ return $this;
+ }
+
+ /**
+ * Creates a new generic LDAP entry instance.
+ *
+ * @param array $attributes
+ *
+ * @return Entry
+ */
+ public function entry(array $attributes = [])
+ {
+ $model = $this->schema->entryModel();
+
+ return new $model($attributes, $this->query);
+ }
+
+ /**
+ * Creates a new user instance.
+ *
+ * @param array $attributes
+ *
+ * @return User
+ */
+ public function user(array $attributes = [])
+ {
+ $model = $this->schema->userModel();
+
+ return (new $model($attributes, $this->query))
+ ->setAttribute($this->schema->objectClass(), $this->schema->userObjectClasses());
+ }
+
+ /**
+ * Creates a new organizational unit instance.
+ *
+ * @param array $attributes
+ *
+ * @return OrganizationalUnit
+ */
+ public function ou(array $attributes = [])
+ {
+ $model = $this->schema->organizationalUnitModel();
+
+ return (new $model($attributes, $this->query))
+ ->setAttribute($this->schema->objectClass(), [
+ $this->schema->top(),
+ $this->schema->organizationalUnit(),
+ ]);
+ }
+
+ /**
+ * Creates a new organizational unit instance.
+ *
+ * @param array $attributes
+ *
+ * @return Organization
+ */
+ public function organization(array $attributes = [])
+ {
+ $model = $this->schema->organizationModel();
+
+ return (new $model($attributes, $this->query))
+ ->setAttribute($this->schema->objectClass(), [
+ $this->schema->top(),
+ $this->schema->organization(),
+ ]);
+ }
+
+ /**
+ * Creates a new group instance.
+ *
+ * @param array $attributes
+ *
+ * @return Group
+ */
+ public function group(array $attributes = [])
+ {
+ $model = $this->schema->groupModel();
+
+ return (new $model($attributes, $this->query))
+ ->setAttribute($this->schema->objectClass(), [
+ $this->schema->top(),
+ $this->schema->objectCategoryGroup(),
+ ]);
+ }
+
+ /**
+ * Creates a new organizational unit instance.
+ *
+ * @param array $attributes
+ *
+ * @return Container
+ */
+ public function container(array $attributes = [])
+ {
+ $model = $this->schema->containerModel();
+
+ return (new $model($attributes, $this->query))
+ ->setAttribute($this->schema->objectClass(), $this->schema->objectClassContainer());
+ }
+
+ /**
+ * Creates a new user instance as a contact.
+ *
+ * @param array $attributes
+ *
+ * @return User
+ */
+ public function contact(array $attributes = [])
+ {
+ $model = $this->schema->contactModel();
+
+ return (new $model($attributes, $this->query))
+ ->setAttribute($this->schema->objectClass(), [
+ $this->schema->top(),
+ $this->schema->person(),
+ $this->schema->organizationalPerson(),
+ $this->schema->contact(),
+ ]);
+ }
+
+ /**
+ * Creates a new computer instance.
+ *
+ * @param array $attributes
+ *
+ * @return Computer
+ */
+ public function computer(array $attributes = [])
+ {
+ $model = $this->schema->computerModel();
+
+ return (new $model($attributes, $this->query))
+ ->setAttribute($this->schema->objectClass(), [
+ $this->schema->top(),
+ $this->schema->person(),
+ $this->schema->organizationalPerson(),
+ $this->schema->user(),
+ $this->schema->computer(),
+ ]);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/ForeignSecurityPrincipal.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/ForeignSecurityPrincipal.php
new file mode 100644
index 0000000..b0d15d8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/ForeignSecurityPrincipal.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Adldap\Models;
+
+/**
+ * Class ForeignSecurityPrincipal.
+ *
+ * Represents an LDAP ForeignSecurityPrincipal.
+ */
+class ForeignSecurityPrincipal extends Entry
+{
+ use Concerns\HasMemberOf;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Group.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Group.php
new file mode 100644
index 0000000..7a89457
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Group.php
@@ -0,0 +1,288 @@
+<?php
+
+namespace Adldap\Models;
+
+use Adldap\Utilities;
+use InvalidArgumentException;
+
+/**
+ * Class Group.
+ *
+ * Represents an LDAP group (security / distribution).
+ */
+class Group extends Entry
+{
+ use Concerns\HasMemberOf;
+ use Concerns\HasDescription;
+
+ /**
+ * Returns all users apart of the current group.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms677097(v=vs.85).aspx
+ *
+ * @return \Adldap\Query\Collection
+ */
+ public function getMembers()
+ {
+ $members = $this->getMembersFromAttribute($this->schema->member());
+
+ if (count($members) === 0) {
+ $members = $this->getPaginatedMembers();
+ }
+
+ return $this->newCollection($members);
+ }
+
+ /**
+ * Returns the group's member names only.
+ *
+ * @return array
+ */
+ public function getMemberNames()
+ {
+ $members = [];
+
+ $dns = $this->getAttribute($this->schema->member()) ?: [];
+
+ foreach ($dns as $dn) {
+ $exploded = Utilities::explodeDn($dn);
+
+ if (array_key_exists(0, $exploded)) {
+ $members[] = $exploded[0];
+ }
+ }
+
+ return $members;
+ }
+
+ /**
+ * Sets the groups members using an array of user DNs.
+ *
+ * @param array $entries
+ *
+ * @return $this
+ */
+ public function setMembers(array $entries)
+ {
+ return $this->setAttribute($this->schema->member(), $entries);
+ }
+
+ /**
+ * Adds multiple entries to the current group.
+ *
+ * @param array $members
+ *
+ * @return bool
+ */
+ public function addMembers(array $members)
+ {
+ $members = array_map(function ($member) {
+ return $member instanceof Model
+ ? $member->getDn()
+ : $member;
+ }, $members);
+
+ $mod = $this->newBatchModification(
+ $this->schema->member(),
+ LDAP_MODIFY_BATCH_ADD,
+ $members
+ );
+
+ return $this->addModification($mod)->save();
+ }
+
+ /**
+ * Adds an entry to the current group.
+ *
+ * @param string|Entry $member
+ *
+ * @throws InvalidArgumentException When the given entry is empty or contains no distinguished name.
+ *
+ * @return bool
+ */
+ public function addMember($member)
+ {
+ $member = ($member instanceof Model ? $member->getDn() : $member);
+
+ if (is_null($member)) {
+ throw new InvalidArgumentException(
+ 'Cannot add member to group. The members distinguished name cannot be null.'
+ );
+ }
+
+ $mod = $this->newBatchModification(
+ $this->schema->member(),
+ LDAP_MODIFY_BATCH_ADD,
+ [$member]
+ );
+
+ return $this->addModification($mod)->save();
+ }
+
+ /**
+ * Removes an entry from the current group.
+ *
+ * @param string|Entry $member
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return bool
+ */
+ public function removeMember($member)
+ {
+ $member = ($member instanceof Model ? $member->getDn() : $member);
+
+ if (is_null($member)) {
+ throw new InvalidArgumentException(
+ 'Cannot remove member to group. The members distinguished name cannot be null.'
+ );
+ }
+
+ $mod = $this->newBatchModification(
+ $this->schema->member(),
+ LDAP_MODIFY_BATCH_REMOVE,
+ [$member]
+ );
+
+ return $this->addModification($mod)->save();
+ }
+
+ /**
+ * Removes all members from the current group.
+ *
+ * @return bool
+ */
+ public function removeMembers()
+ {
+ $mod = $this->newBatchModification(
+ $this->schema->member(),
+ LDAP_MODIFY_BATCH_REMOVE_ALL
+ );
+
+ return $this->addModification($mod)->save();
+ }
+
+ /**
+ * Returns the group type integer.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675935(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getGroupType()
+ {
+ return $this->getFirstAttribute($this->schema->groupType());
+ }
+
+ /**
+ * Retrieves group members by the specified model attribute.
+ *
+ * @param $attribute
+ *
+ * @return array
+ */
+ protected function getMembersFromAttribute($attribute)
+ {
+ $members = [];
+
+ $entries = $this->getAttribute($attribute) ?: [];
+
+ $query = $this->query->newInstance();
+
+ // Retrieving the member identifier to allow
+ // compatibility with LDAP variants.
+ $identifier = $this->schema->memberIdentifier();
+
+ foreach ($entries as $entry) {
+ // If our identifier is a distinguished name, then we need to
+ // use an alternate query method, as we can't locate records
+ // by distinguished names using an LDAP filter.
+ if ($identifier == 'dn' || $identifier == 'distinguishedname') {
+ $member = $query->findByDn($entry);
+ } else {
+ // We'll ensure we clear our filters when retrieving each member,
+ // so we can continue fetching the next one in line.
+ $member = $query->clearFilters()->findBy($identifier, $entry);
+ }
+
+ // We'll double check that we've received a model from
+ // our query before adding it into our results.
+ if ($member instanceof Model) {
+ $members[] = $member;
+ }
+ }
+
+ return $members;
+ }
+
+ /**
+ * Retrieves members that are contained in a member range.
+ *
+ * @return array
+ */
+ protected function getPaginatedMembers()
+ {
+ $members = [];
+
+ $keys = array_keys($this->attributes);
+
+ // We need to filter out the model attributes so
+ // we only retrieve the member range.
+ $attributes = array_values(array_filter($keys, function ($key) {
+ return strpos($key, 'member;range') !== false;
+ }));
+
+ // We'll grab the member range key so we can run a
+ // regex on it to determine the range.
+ $key = reset($attributes);
+
+ preg_match_all(
+ '/member;range\=([0-9]{1,4})-([0-9*]{1,4})/',
+ $key,
+ $matches
+ );
+
+ if ($key && count($matches) == 3) {
+ // Retrieve the ending range number.
+ $to = $matches[2][0];
+
+ // Retrieve the current groups members from the
+ // current range string (ex. 'member;0-50').
+ $members = $this->getMembersFromAttribute($key);
+
+ // If the query already included all member results (indicated
+ // by the '*'), then we can return here. Otherwise we need
+ // to continue on and retrieve the rest.
+ if ($to === '*') {
+ return $members;
+ }
+
+ // Determine the amount of members we're requesting per query.
+ $range = $to - $matches[1][0];
+
+ // Set our starting range to our last end range plus one.
+ $from = $to + 1;
+
+ // We'll determine the new end range by adding the
+ // total range to our new starting range.
+ $to = $from + $range;
+
+ // We'll need to query for the current model again but with
+ // a new range to retrieve the other members.
+ /** @var Group $group */
+ $group = $this->query->newInstance()->findByDn(
+ $this->getDn(),
+ [$this->query->getSchema()->memberRange($from, $to)]
+ );
+
+ // Finally, we'll merge our current members
+ // with the newly returned members.
+ $members = array_merge(
+ $members,
+ $group->getMembers()->toArray()
+ );
+ }
+
+ return $members;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Model.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Model.php
new file mode 100644
index 0000000..3bad2ea
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Model.php
@@ -0,0 +1,1266 @@
+<?php
+
+namespace Adldap\Models;
+
+use DateTime;
+use ArrayAccess;
+use Adldap\Utilities;
+use JsonSerializable;
+use Adldap\Query\Builder;
+use Illuminate\Support\Arr;
+use Adldap\Query\Collection;
+use InvalidArgumentException;
+use UnexpectedValueException;
+use Adldap\Models\Attributes\Sid;
+use Adldap\Models\Attributes\Guid;
+use Adldap\Schemas\SchemaInterface;
+use Adldap\Models\Attributes\MbString;
+use Adldap\Connections\ConnectionException;
+use Adldap\Models\Attributes\DistinguishedName;
+
+/**
+ * Class Model.
+ *
+ * Represents an LDAP record and provides the ability
+ * to modify / retrieve data from the record.
+ */
+abstract class Model implements ArrayAccess, JsonSerializable
+{
+ use Concerns\HasEvents;
+ use Concerns\HasAttributes;
+
+ /**
+ * Indicates if the model exists.
+ *
+ * @var bool
+ */
+ public $exists = false;
+
+ /**
+ * The current query builder instance.
+ *
+ * @var Builder
+ */
+ protected $query;
+
+ /**
+ * The current LDAP attribute schema.
+ *
+ * @var SchemaInterface
+ */
+ protected $schema;
+
+ /**
+ * Contains the models modifications.
+ *
+ * @var array
+ */
+ protected $modifications = [];
+
+ /**
+ * Constructor.
+ *
+ * @param array $attributes
+ * @param Builder $builder
+ */
+ public function __construct(array $attributes, Builder $builder)
+ {
+ $this->setQuery($builder)
+ ->setSchema($builder->getSchema())
+ ->fill($attributes);
+ }
+
+ /**
+ * Returns the models distinguished name when the model is converted to a string.
+ *
+ * @return null|string
+ */
+ public function __toString()
+ {
+ return $this->getDn();
+ }
+
+ /**
+ * Sets the current query builder.
+ *
+ * @param Builder $builder
+ *
+ * @return $this
+ */
+ public function setQuery(Builder $builder)
+ {
+ $this->query = $builder;
+
+ return $this;
+ }
+
+ /**
+ * Returns the current query builder.
+ *
+ * @return Builder
+ */
+ public function getQuery()
+ {
+ return $this->query;
+ }
+
+ /**
+ * Returns a new query builder instance.
+ *
+ * @return Builder
+ */
+ public function newQuery()
+ {
+ return $this->query->newInstance();
+ }
+
+ /**
+ * Returns a new batch modification.
+ *
+ * @param string|null $attribute
+ * @param string|int|null $type
+ * @param array $values
+ *
+ * @return BatchModification
+ */
+ public function newBatchModification($attribute = null, $type = null, $values = [])
+ {
+ return new BatchModification($attribute, $type, $values);
+ }
+
+ /**
+ * Returns a new collection with the specified items.
+ *
+ * @param mixed $items
+ *
+ * @return Collection
+ */
+ public function newCollection($items = [])
+ {
+ return new Collection($items);
+ }
+
+ /**
+ * Sets the current model schema.
+ *
+ * @param SchemaInterface $schema
+ *
+ * @return $this
+ */
+ public function setSchema(SchemaInterface $schema)
+ {
+ $this->schema = $schema;
+
+ return $this;
+ }
+
+ /**
+ * Returns the current model schema.
+ *
+ * @return SchemaInterface
+ */
+ public function getSchema()
+ {
+ return $this->schema;
+ }
+
+ /**
+ * Determine if the given offset exists.
+ *
+ * @param string $offset
+ *
+ * @return bool
+ */
+ public function offsetExists($offset)
+ {
+ return !is_null($this->getAttribute($offset));
+ }
+
+ /**
+ * Get the value for a given offset.
+ *
+ * @param string $offset
+ *
+ * @return mixed
+ */
+ public function offsetGet($offset)
+ {
+ return $this->getAttribute($offset);
+ }
+
+ /**
+ * Set the value at the given offset.
+ *
+ * @param string $offset
+ * @param mixed $value
+ *
+ * @return void
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->setAttribute($offset, $value);
+ }
+
+ /**
+ * Unset the value at the given offset.
+ *
+ * @param string $offset
+ *
+ * @return void
+ */
+ public function offsetUnset($offset)
+ {
+ unset($this->attributes[$offset]);
+ }
+
+ /**
+ * Determine if an attribute exists on the model.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function __isset($key)
+ {
+ return $this->offsetExists($key);
+ }
+
+ /**
+ * Convert the object into something JSON serializable.
+ *
+ * @return array
+ */
+ public function jsonSerialize()
+ {
+ $attributes = $this->getAttributes();
+
+ array_walk_recursive($attributes, function (&$val) {
+ if (MbString::isLoaded()) {
+ // If we're able to detect the attribute
+ // encoding, we'll encode only the
+ // attributes that need to be.
+ if (!MbString::isUtf8($val)) {
+ $val = utf8_encode($val);
+ }
+ } else {
+ // If the mbstring extension is not loaded, we'll
+ // encode all attributes to make sure
+ // they are encoded properly.
+ $val = utf8_encode($val);
+ }
+ });
+
+ // We'll replace the binary GUID and SID with
+ // their string equivalents for convenience.
+ return array_replace($attributes, [
+ $this->schema->objectGuid() => $this->getConvertedGuid(),
+ $this->schema->objectSid() => $this->getConvertedSid(),
+ ]);
+ }
+
+ /**
+ * Reload a fresh model instance from the directory.
+ *
+ * @return static|null
+ */
+ public function fresh()
+ {
+ $model = $this->query->newInstance()->findByDn($this->getDn());
+
+ return $model instanceof self ? $model : null;
+ }
+
+ /**
+ * Synchronizes the current models attributes with the directory values.
+ *
+ * @return bool
+ */
+ public function syncRaw()
+ {
+ if ($model = $this->fresh()) {
+ $this->setRawAttributes($model->getAttributes());
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the models batch modifications to be processed.
+ *
+ * @return array
+ */
+ public function getModifications()
+ {
+ $this->buildModificationsFromDirty();
+
+ return $this->modifications;
+ }
+
+ /**
+ * Sets the models modifications array.
+ *
+ * @param array $modifications
+ *
+ * @return $this
+ */
+ public function setModifications(array $modifications = [])
+ {
+ $this->modifications = $modifications;
+
+ return $this;
+ }
+
+ /**
+ * Adds a batch modification to the models modifications array.
+ *
+ * @param array|BatchModification $mod
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function addModification($mod = [])
+ {
+ if ($mod instanceof BatchModification) {
+ $mod = $mod->get();
+ }
+
+ if ($this->isValidModification($mod)) {
+ $this->modifications[] = $mod;
+
+ return $this;
+ }
+
+ throw new InvalidArgumentException(
+ "The batch modification array does not include the mandatory 'attrib' or 'modtype' keys."
+ );
+ }
+
+ /**
+ * Returns the model's distinguished name string.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/aa366101(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getDistinguishedName()
+ {
+ return $this->getFirstAttribute($this->schema->distinguishedName());
+ }
+
+ /**
+ * Sets the model's distinguished name attribute.
+ *
+ * @param string|DistinguishedName $dn
+ *
+ * @return $this
+ */
+ public function setDistinguishedName($dn)
+ {
+ $this->setFirstAttribute($this->schema->distinguishedName(), (string) $dn);
+
+ return $this;
+ }
+
+ /**
+ * Returns the model's distinguished name string.
+ *
+ * (Alias for getDistinguishedName())
+ *
+ * @link https://msdn.microsoft.com/en-us/library/aa366101(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getDn()
+ {
+ return $this->getDistinguishedName();
+ }
+
+ /**
+ * Returns a DistinguishedName object for modifying the current models DN.
+ *
+ * @return DistinguishedName
+ */
+ public function getDnBuilder()
+ {
+ // If we currently don't have a distinguished name, we'll set
+ // it to our base, otherwise we'll use our query's base DN.
+ $dn = $this->getDistinguishedName() ?: $this->query->getDn();
+
+ return $this->getNewDnBuilder($dn);
+ }
+
+ /**
+ * Returns the models distinguished name components.
+ *
+ * @param bool $removeAttributePrefixes
+ *
+ * @return array
+ */
+ public function getDnComponents($removeAttributePrefixes = true)
+ {
+ if ($components = Utilities::explodeDn($this->getDn(), $removeAttributePrefixes)) {
+ unset($components['count']);
+
+ return $components;
+ }
+
+ return [];
+ }
+
+ /**
+ * Returns the distinguished name that the model is a leaf of.
+ *
+ * @return string
+ */
+ public function getDnRoot()
+ {
+ $components = $this->getDnComponents(false);
+
+ // Shift off the beginning of the array;
+ // This contains the models RDN.
+ array_shift($components);
+
+ return implode(',', $components);
+ }
+
+ /**
+ * Returns a new DistinguishedName object for building onto.
+ *
+ * @param string $baseDn
+ *
+ * @return DistinguishedName
+ */
+ public function getNewDnBuilder($baseDn = '')
+ {
+ return new DistinguishedName($baseDn);
+ }
+
+ /**
+ * Sets the model's distinguished name attribute.
+ *
+ * (Alias for setDistinguishedName())
+ *
+ * @param string $dn
+ *
+ * @return $this
+ */
+ public function setDn($dn)
+ {
+ return $this->setDistinguishedName($dn);
+ }
+
+ /**
+ * Returns the model's hex object SID.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679024(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getObjectSid()
+ {
+ return $this->getFirstAttribute($this->schema->objectSid());
+ }
+
+ /**
+ * Returns the model's binary object GUID.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679021(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getObjectGuid()
+ {
+ return $this->getFirstAttribute($this->schema->objectGuid());
+ }
+
+ /**
+ * Returns the model's GUID.
+ *
+ * @return string|null
+ */
+ public function getConvertedGuid()
+ {
+ try {
+ return (string) new Guid($this->getObjectGuid());
+ } catch (InvalidArgumentException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Returns the model's SID.
+ *
+ * @return string|null
+ */
+ public function getConvertedSid()
+ {
+ try {
+ return (string) new Sid($this->getObjectSid());
+ } catch (InvalidArgumentException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Returns the model's common name.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675449(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getCommonName()
+ {
+ return $this->getFirstAttribute($this->schema->commonName());
+ }
+
+ /**
+ * Sets the model's common name.
+ *
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function setCommonName($name)
+ {
+ return $this->setFirstAttribute($this->schema->commonName(), $name);
+ }
+
+ /**
+ * Returns the model's name. An LDAP alias for the CN attribute.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675449(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->getFirstAttribute($this->schema->name());
+ }
+
+ /**
+ * Sets the model's name.
+ *
+ * @param string $name
+ *
+ * @return Model
+ */
+ public function setName($name)
+ {
+ return $this->setFirstAttribute($this->schema->name(), $name);
+ }
+
+ /**
+ * Returns the model's display name.
+ *
+ * @return string
+ */
+ public function getDisplayName()
+ {
+ return $this->getFirstAttribute($this->schema->displayName());
+ }
+
+ /**
+ * Sets the model's display name.
+ *
+ * @param string $displayName
+ *
+ * @return $this
+ */
+ public function setDisplayName($displayName)
+ {
+ return $this->setFirstAttribute($this->schema->displayName(), $displayName);
+ }
+
+ /**
+ * Returns the model's samaccountname.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679635(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getAccountName()
+ {
+ return $this->getFirstAttribute($this->schema->accountName());
+ }
+
+ /**
+ * Sets the model's samaccountname.
+ *
+ * @param string $accountName
+ *
+ * @return Model
+ */
+ public function setAccountName($accountName)
+ {
+ return $this->setFirstAttribute($this->schema->accountName(), $accountName);
+ }
+
+ /**
+ * Returns the model's userPrincipalName.
+ *
+ * @link https://docs.microsoft.com/en-us/windows/win32/adschema/a-userprincipalname
+ *
+ * @return string
+ */
+ public function getUserPrincipalName()
+ {
+ return $this->getFirstAttribute($this->schema->userPrincipalName());
+ }
+
+ /**
+ * Sets the model's userPrincipalName.
+ *
+ * @param string $upn
+ *
+ * @return Model
+ */
+ public function setUserPrincipalName($upn)
+ {
+ return $this->setFirstAttribute($this->schema->userPrincipalName(), $upn);
+ }
+
+ /**
+ * Returns the model's samaccounttype.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679637(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getAccountType()
+ {
+ return $this->getFirstAttribute($this->schema->accountType());
+ }
+
+ /**
+ * Returns the model's `whenCreated` time.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680924(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getCreatedAt()
+ {
+ return $this->getFirstAttribute($this->schema->createdAt());
+ }
+
+ /**
+ * Returns the created at time in a mysql formatted date.
+ *
+ * @return string
+ */
+ public function getCreatedAtDate()
+ {
+ return (new DateTime())->setTimestamp($this->getCreatedAtTimestamp())->format($this->dateFormat);
+ }
+
+ /**
+ * Returns the created at time in a unix timestamp format.
+ *
+ * @return float
+ */
+ public function getCreatedAtTimestamp()
+ {
+ return DateTime::createFromFormat($this->timestampFormat, $this->getCreatedAt())->getTimestamp();
+ }
+
+ /**
+ * Returns the model's `whenChanged` time.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680921(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getUpdatedAt()
+ {
+ return $this->getFirstAttribute($this->schema->updatedAt());
+ }
+
+ /**
+ * Returns the updated at time in a mysql formatted date.
+ *
+ * @return string
+ */
+ public function getUpdatedAtDate()
+ {
+ return (new DateTime())->setTimestamp($this->getUpdatedAtTimestamp())->format($this->dateFormat);
+ }
+
+ /**
+ * Returns the updated at time in a unix timestamp format.
+ *
+ * @return float
+ */
+ public function getUpdatedAtTimestamp()
+ {
+ return DateTime::createFromFormat($this->timestampFormat, $this->getUpdatedAt())->getTimestamp();
+ }
+
+ /**
+ * Returns the Container of the current Model.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679012(v=vs.85).aspx
+ *
+ * @return Container|Entry|bool
+ */
+ public function getObjectClass()
+ {
+ return $this->query->findByDn($this->getObjectCategoryDn());
+ }
+
+ /**
+ * Returns the CN of the model's object category.
+ *
+ * @return null|string
+ */
+ public function getObjectCategory()
+ {
+ $category = $this->getObjectCategoryArray();
+
+ if (is_array($category) && array_key_exists(0, $category)) {
+ return $category[0];
+ }
+ }
+
+ /**
+ * Returns the model's object category DN in an exploded array.
+ *
+ * @return array|false
+ */
+ public function getObjectCategoryArray()
+ {
+ return Utilities::explodeDn($this->getObjectCategoryDn());
+ }
+
+ /**
+ * Returns the model's object category DN string.
+ *
+ * @return null|string
+ */
+ public function getObjectCategoryDn()
+ {
+ return $this->getFirstAttribute($this->schema->objectCategory());
+ }
+
+ /**
+ * Returns the model's primary group ID.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679375(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPrimaryGroupId()
+ {
+ return $this->getFirstAttribute($this->schema->primaryGroupId());
+ }
+
+ /**
+ * Returns the model's instance type.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676204(v=vs.85).aspx
+ *
+ * @return int
+ */
+ public function getInstanceType()
+ {
+ return $this->getFirstAttribute($this->schema->instanceType());
+ }
+
+ /**
+ * Returns the distinguished name of the user who is assigned to manage this object.
+ *
+ * @return string|null
+ */
+ public function getManagedBy()
+ {
+ return $this->getFirstAttribute($this->schema->managedBy());
+ }
+
+ /**
+ * Returns the user model of the user who is assigned to manage this object.
+ *
+ * Returns false otherwise.
+ *
+ * @return User|bool
+ */
+ public function getManagedByUser()
+ {
+ if ($dn = $this->getManagedBy()) {
+ return $this->query->newInstance()->findByDn($dn);
+ }
+
+ return false;
+ }
+
+ /**
+ * Sets the user who is assigned to managed this object.
+ *
+ * @param Model|string $dn
+ *
+ * @return $this
+ */
+ public function setManagedBy($dn)
+ {
+ if ($dn instanceof self) {
+ $dn = $dn->getDn();
+ }
+
+ return $this->setFirstAttribute($this->schema->managedBy(), $dn);
+ }
+
+ /**
+ * Returns the model's max password age.
+ *
+ * @return string
+ */
+ public function getMaxPasswordAge()
+ {
+ return $this->getFirstAttribute($this->schema->maxPasswordAge());
+ }
+
+ /**
+ * Returns the model's max password age in days.
+ *
+ * @return int
+ */
+ public function getMaxPasswordAgeDays()
+ {
+ $age = $this->getMaxPasswordAge();
+
+ return (int) (abs($age) / 10000000 / 60 / 60 / 24);
+ }
+
+ /**
+ * Determine if the current model is located inside the given OU.
+ *
+ * If a model instance is given, the strict parameter is ignored.
+ *
+ * @param Model|string $ou The organizational unit to check.
+ * @param bool $strict Whether the check is case-sensitive.
+ *
+ * @return bool
+ */
+ public function inOu($ou, $strict = false)
+ {
+ if ($ou instanceof self) {
+ // If we've been given an OU model, we can
+ // just check if the OU's DN is inside
+ // the current models DN.
+ return (bool) strpos($this->getDn(), $ou->getDn());
+ }
+
+ $suffix = $strict ? '' : 'i';
+
+ return (bool) preg_grep("/{$ou}/{$suffix}", $this->getDnBuilder()->getComponents('ou'));
+ }
+
+ /**
+ * Returns true / false if the current model is writable
+ * by checking its instance type integer.
+ *
+ * @return bool
+ */
+ public function isWritable()
+ {
+ return (int) $this->getInstanceType() === 4;
+ }
+
+ /**
+ * Saves the changes to LDAP and returns the results.
+ *
+ * @param array $attributes The attributes to update or create for the current entry.
+ *
+ * @return bool
+ */
+ public function save(array $attributes = [])
+ {
+ $this->fireModelEvent(new Events\Saving($this));
+
+ $saved = $this->exists ? $this->update($attributes) : $this->create($attributes);
+
+ if ($saved) {
+ $this->fireModelEvent(new Events\Saved($this));
+ }
+
+ return $saved;
+ }
+
+ /**
+ * Updates the model.
+ *
+ * @param array $attributes The attributes to update for the current entry.
+ *
+ * @return bool
+ */
+ public function update(array $attributes = [])
+ {
+ $this->fill($attributes);
+
+ $modifications = $this->getModifications();
+
+ if (count($modifications) > 0) {
+ $this->fireModelEvent(new Events\Updating($this));
+
+ // Push the update.
+ if ($this->query->getConnection()->modifyBatch($this->getDn(), $modifications)) {
+ // Re-sync attributes.
+ $this->syncRaw();
+
+ $this->fireModelEvent(new Events\Updated($this));
+
+ // Re-set the models modifications.
+ $this->modifications = [];
+
+ return true;
+ }
+
+ // Modification failed, return false.
+ return false;
+ }
+
+ // We need to return true here because modify batch will
+ // return false if no modifications are made
+ // but this may not always be the case.
+ return true;
+ }
+
+ /**
+ * Creates the entry in LDAP.
+ *
+ * @param array $attributes The attributes for the new entry.
+ *
+ * @throws UnexpectedValueException
+ *
+ * @return bool
+ */
+ public function create(array $attributes = [])
+ {
+ $this->fill($attributes);
+
+ if (empty($this->getDn())) {
+ // If the model doesn't currently have a distinguished
+ // name set, we'll create one automatically using
+ // the current query builders base DN.
+ $dn = $this->getCreatableDn();
+
+ // If the dn we receive is the same as our queries base DN, we need
+ // to throw an exception. The LDAP object must have a valid RDN.
+ if ($dn->get() == $this->query->getDn()) {
+ throw new UnexpectedValueException("An LDAP object must have a valid RDN to be created. '$dn' given.");
+ }
+
+ $this->setDn($dn);
+ }
+
+ $this->fireModelEvent(new Events\Creating($this));
+
+ // Create the entry.
+ $created = $this->query->getConnection()->add($this->getDn(), $this->getCreatableAttributes());
+
+ if ($created) {
+ // If the entry was created we'll re-sync
+ // the models attributes from the server.
+ $this->syncRaw();
+
+ $this->fireModelEvent(new Events\Created($this));
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Creates an attribute on the current model.
+ *
+ * @param string $attribute The attribute to create
+ * @param mixed $value The value of the new attribute
+ * @param bool $sync Whether to re-sync all attributes
+ *
+ * @return bool
+ */
+ public function createAttribute($attribute, $value, $sync = true)
+ {
+ if (
+ $this->exists &&
+ $this->query->getConnection()->modAdd($this->getDn(), [$attribute => $value])
+ ) {
+ if ($sync) {
+ $this->syncRaw();
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Updates the specified attribute with the specified value.
+ *
+ * @param string $attribute The attribute to modify
+ * @param mixed $value The new value for the attribute
+ * @param bool $sync Whether to re-sync all attributes
+ *
+ * @return bool
+ */
+ public function updateAttribute($attribute, $value, $sync = true)
+ {
+ if (
+ $this->exists &&
+ $this->query->getConnection()->modReplace($this->getDn(), [$attribute => $value])
+ ) {
+ if ($sync) {
+ $this->syncRaw();
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Deletes an attribute on the current entry.
+ *
+ * @param string|array $attributes The attribute(s) to delete
+ * @param bool $sync Whether to re-sync all attributes
+ *
+ * Delete specific values in attributes:
+ *
+ * ["memberuid" => "username"]
+ *
+ * Delete an entire attribute:
+ *
+ * ["memberuid" => []]
+ *
+ * @return bool
+ */
+ public function deleteAttribute($attributes, $sync = true)
+ {
+ // If we've been given a string, we'll assume we're removing a
+ // single attribute. Otherwise, we'll assume it's
+ // an array of attributes to remove.
+ $attributes = is_string($attributes) ? [$attributes => []] : $attributes;
+
+ if (
+ $this->exists &&
+ $this->query->getConnection()->modDelete($this->getDn(), $attributes)
+ ) {
+ if ($sync) {
+ $this->syncRaw();
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Deletes the current entry.
+ *
+ * Throws a ModelNotFoundException if the current model does
+ * not exist or does not contain a distinguished name.
+ *
+ * @param bool $recursive Whether to recursively delete leaf nodes (models that are children).
+ *
+ * @throws ModelDoesNotExistException
+ *
+ * @return bool
+ */
+ public function delete($recursive = false)
+ {
+ $dn = $this->getDn();
+
+ if ($this->exists === false || empty($dn)) {
+ // Make sure the record exists before we can delete it.
+ // Otherwise, we'll throw an exception.
+ throw (new ModelDoesNotExistException())->setModel(get_class($this));
+ }
+
+ $this->fireModelEvent(new Events\Deleting($this));
+
+ if ($recursive) {
+ // If recursive is requested, we'll retrieve all direct leaf nodes
+ // by executing a 'listing' and delete each resulting model.
+ $this->newQuery()->listing()->in($this->getDn())->get()->each(function (self $model) use ($recursive) {
+ $model->delete($recursive);
+ });
+ }
+
+ if ($this->query->getConnection()->delete($dn)) {
+ // If the deletion was successful, we'll mark the model
+ // as non-existing and fire the deleted event.
+ $this->exists = false;
+
+ $this->fireModelEvent(new Events\Deleted($this));
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Moves the current model into the given new parent.
+ *
+ * For example: $user->move($ou);
+ *
+ * @param Model|string $newParentDn The new parent of the current model.
+ * @param bool $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
+ *
+ * @return bool
+ */
+ public function move($newParentDn, $deleteOldRdn = true)
+ {
+ // First we'll explode the current models distinguished name and keep their attributes prefixes.
+ $parts = Utilities::explodeDn($this->getDn(), $removeAttrPrefixes = false);
+
+ // If the current model has an empty RDN, we can't move it.
+ if ((int) Arr::first($parts) === 0) {
+ throw new UnexpectedValueException('Current model does not contain an RDN to move.');
+ }
+
+ // Looks like we have a DN. We'll retrieve the leftmost RDN (the identifier).
+ $rdn = Arr::get($parts, 0);
+
+ return $this->rename($rdn, $newParentDn, $deleteOldRdn);
+ }
+
+ /**
+ * Renames the current model to a new RDN and new parent.
+ *
+ * @param string $rdn The models new relative distinguished name. Example: "cn=JohnDoe"
+ * @param Model|string|null $newParentDn The models new parent distinguished name (if moving). Leave this null if you are only renaming. Example: "ou=MovedUsers,dc=acme,dc=org"
+ * @param bool|true $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
+ *
+ * @return bool
+ */
+ public function rename($rdn, $newParentDn = null, $deleteOldRdn = true)
+ {
+ if ($newParentDn instanceof self) {
+ $newParentDn = $newParentDn->getDn();
+ }
+
+ $moved = $this->query->getConnection()->rename($this->getDn(), $rdn, $newParentDn, $deleteOldRdn);
+
+ if ($moved) {
+ // If the model was successfully moved, we'll set its
+ // new DN so we can sync it's attributes properly.
+ $this->setDn("{$rdn},{$newParentDn}");
+
+ $this->syncRaw();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Constructs a new distinguished name that is creatable in the directory.
+ *
+ * @return DistinguishedName|string
+ */
+ protected function getCreatableDn()
+ {
+ return $this->getDnBuilder()->addCn($this->getCommonName());
+ }
+
+ /**
+ * Returns the models creatable attributes.
+ *
+ * @return mixed
+ */
+ protected function getCreatableAttributes()
+ {
+ return Arr::except($this->getAttributes(), [$this->schema->distinguishedName()]);
+ }
+
+ /**
+ * Determines if the given modification is valid.
+ *
+ * @param mixed $mod
+ *
+ * @return bool
+ */
+ protected function isValidModification($mod)
+ {
+ return is_array($mod) &&
+ array_key_exists(BatchModification::KEY_MODTYPE, $mod) &&
+ array_key_exists(BatchModification::KEY_ATTRIB, $mod);
+ }
+
+ /**
+ * Builds the models modifications from its dirty attributes.
+ *
+ * @return array
+ */
+ protected function buildModificationsFromDirty()
+ {
+ foreach ($this->getDirty() as $attribute => $values) {
+ // Make sure values is always an array.
+ $values = (is_array($values) ? $values : [$values]);
+
+ // Create a new modification.
+ $modification = $this->newBatchModification($attribute, null, $values);
+
+ if (array_key_exists($attribute, $this->original)) {
+ // If the attribute we're modifying has an original value, we'll give the
+ // BatchModification object its values to automatically determine
+ // which type of LDAP operation we need to perform.
+ $modification->setOriginal($this->original[$attribute]);
+ }
+
+ // Build the modification from its
+ // possible original values.
+ $modification->build();
+
+ if ($modification->isValid()) {
+ // Finally, we'll add the modification to the model.
+ $this->addModification($modification);
+ }
+ }
+
+ return $this->modifications;
+ }
+
+ /**
+ * Validates that the current LDAP connection is secure.
+ *
+ * @throws ConnectionException
+ *
+ * @return void
+ */
+ protected function validateSecureConnection()
+ {
+ if (!$this->query->getConnection()->canChangePasswords()) {
+ throw new ConnectionException(
+ 'You must be connected to your LDAP server with TLS or SSL to perform this operation.'
+ );
+ }
+ }
+
+ /**
+ * Converts the inserted string boolean to a PHP boolean.
+ *
+ * @param string $bool
+ *
+ * @return null|bool
+ */
+ protected function convertStringToBool($bool)
+ {
+ $bool = strtoupper($bool);
+
+ if ($bool === strtoupper($this->schema->false())) {
+ return false;
+ } elseif ($bool === strtoupper($this->schema->true())) {
+ return true;
+ } else {
+ return;
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/ModelDoesNotExistException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/ModelDoesNotExistException.php
new file mode 100644
index 0000000..3935610
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/ModelDoesNotExistException.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Adldap\Models;
+
+use Adldap\AdldapException;
+
+/**
+ * Class ModelDoesNotExistException.
+ *
+ * Thrown when a model being saved / updated does not actually exist.
+ */
+class ModelDoesNotExistException extends AdldapException
+{
+ /**
+ * The class name of the model that does not exist.
+ *
+ * @var string
+ */
+ protected $model;
+
+ /**
+ * Sets the model that does not exist.
+ *
+ * @param string $model
+ *
+ * @return ModelDoesNotExistException
+ */
+ public function setModel($model)
+ {
+ $this->model = $model;
+
+ $this->message = "Model [{$model}] does not exist.";
+
+ return $this;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/ModelNotFoundException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/ModelNotFoundException.php
new file mode 100644
index 0000000..6cc3334
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/ModelNotFoundException.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Adldap\Models;
+
+use Adldap\AdldapException;
+
+/**
+ * Class ModelNotFoundException.
+ *
+ * Thrown when an LDAP record is not found.
+ */
+class ModelNotFoundException extends AdldapException
+{
+ /**
+ * The query filter that was used.
+ *
+ * @var string
+ */
+ protected $query;
+
+ /**
+ * The base DN of the query that was used.
+ *
+ * @var string
+ */
+ protected $baseDn;
+
+ /**
+ * Sets the query that was used.
+ *
+ * @param string $query
+ * @param string $baseDn
+ *
+ * @return ModelNotFoundException
+ */
+ public function setQuery($query, $baseDn)
+ {
+ $this->query = $query;
+ $this->baseDn = $baseDn;
+
+ $this->message = "No LDAP query results for filter: [{$query}] in: [{$baseDn}]";
+
+ return $this;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Organization.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Organization.php
new file mode 100644
index 0000000..88129d0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Organization.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Adldap\Models;
+
+/**
+ * Class Organization.
+ *
+ * Represents an LDAP organization.
+ */
+class Organization extends Entry
+{
+ use Concerns\HasDescription;
+
+ /**
+ * Retrieves the organization units OU attribute.
+ *
+ * @return string
+ */
+ public function getOrganization()
+ {
+ return $this->getFirstAttribute($this->schema->organizationName());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getCreatableDn()
+ {
+ return $this->getDnBuilder()->addO($this->getOrganization());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/OrganizationalUnit.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/OrganizationalUnit.php
new file mode 100644
index 0000000..0571e4d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/OrganizationalUnit.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Adldap\Models;
+
+/**
+ * Class OrganizationalUnit.
+ *
+ * Represents an LDAP organizational unit.
+ */
+class OrganizationalUnit extends Entry
+{
+ use Concerns\HasDescription;
+
+ /**
+ * Retrieves the organization units OU attribute.
+ *
+ * @return string
+ */
+ public function getOu()
+ {
+ return $this->getFirstAttribute($this->schema->organizationalUnitShort());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getCreatableDn()
+ {
+ return $this->getDnBuilder()->addOU($this->getOu());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Printer.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Printer.php
new file mode 100644
index 0000000..e055866
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/Printer.php
@@ -0,0 +1,286 @@
+<?php
+
+namespace Adldap\Models;
+
+/**
+ * Class Printer.
+ *
+ * Represents an LDAP printer.
+ */
+class Printer extends Entry
+{
+ /**
+ * Returns the printers name.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679385(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPrinterName()
+ {
+ return $this->getFirstAttribute($this->schema->printerName());
+ }
+
+ /**
+ * Returns the printers share name.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679408(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPrinterShareName()
+ {
+ return $this->getFirstAttribute($this->schema->printerShareName());
+ }
+
+ /**
+ * Returns the printers memory.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679396(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getMemory()
+ {
+ return $this->getFirstAttribute($this->schema->printerMemory());
+ }
+
+ /**
+ * Returns the printers URL.
+ *
+ * @return string
+ */
+ public function getUrl()
+ {
+ return $this->getFirstAttribute($this->schema->url());
+ }
+
+ /**
+ * Returns the printers location.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676839(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getLocation()
+ {
+ return $this->getFirstAttribute($this->schema->location());
+ }
+
+ /**
+ * Returns the server name that the
+ * current printer is connected to.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679772(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getServerName()
+ {
+ return $this->getFirstAttribute($this->schema->serverName());
+ }
+
+ /**
+ * Returns true / false if the printer can print in color.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679382(v=vs.85).aspx
+ *
+ * @return null|bool
+ */
+ public function getColorSupported()
+ {
+ return $this->convertStringToBool(
+ $this->getFirstAttribute(
+ $this->schema->printerColorSupported()
+ )
+ );
+ }
+
+ /**
+ * Returns true / false if the printer supports duplex printing.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679383(v=vs.85).aspx
+ *
+ * @return null|bool
+ */
+ public function getDuplexSupported()
+ {
+ return $this->convertStringToBool(
+ $this->getFirstAttribute(
+ $this->schema->printerDuplexSupported()
+ )
+ );
+ }
+
+ /**
+ * Returns an array of printer paper types that the printer supports.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679395(v=vs.85).aspx
+ *
+ * @return array
+ */
+ public function getMediaSupported()
+ {
+ return $this->getAttribute($this->schema->printerMediaSupported());
+ }
+
+ /**
+ * Returns true / false if the printer supports stapling.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679410(v=vs.85).aspx
+ *
+ * @return null|bool
+ */
+ public function getStaplingSupported()
+ {
+ return $this->convertStringToBool(
+ $this->getFirstAttribute(
+ $this->schema->printerStaplingSupported()
+ )
+ );
+ }
+
+ /**
+ * Returns an array of the printers bin names.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679380(v=vs.85).aspx
+ *
+ * @return array
+ */
+ public function getPrintBinNames()
+ {
+ return $this->getAttribute($this->schema->printerBinNames());
+ }
+
+ /**
+ * Returns the printers maximum resolution.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679391(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPrintMaxResolution()
+ {
+ return $this->getFirstAttribute($this->schema->printerMaxResolutionSupported());
+ }
+
+ /**
+ * Returns the printers orientations supported.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679402(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPrintOrientations()
+ {
+ return $this->getFirstAttribute($this->schema->printerOrientationSupported());
+ }
+
+ /**
+ * Returns the driver name of the printer.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675652(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getDriverName()
+ {
+ return $this->getFirstAttribute($this->schema->driverName());
+ }
+
+ /**
+ * Returns the printer drivers version number.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675653(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getDriverVersion()
+ {
+ return $this->getFirstAttribute($this->schema->driverVersion());
+ }
+
+ /**
+ * Returns the priority number of the printer.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679413(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPriority()
+ {
+ return $this->getFirstAttribute($this->schema->priority());
+ }
+
+ /**
+ * Returns the printers start time.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679411(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPrintStartTime()
+ {
+ return $this->getFirstAttribute($this->schema->printerStartTime());
+ }
+
+ /**
+ * Returns the printers end time.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679384(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPrintEndTime()
+ {
+ return $this->getFirstAttribute($this->schema->printerEndTime());
+ }
+
+ /**
+ * Returns the port name of printer.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679131(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPortName()
+ {
+ return $this->getFirstAttribute($this->schema->portName());
+ }
+
+ /**
+ * Returns the printers version number.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680897(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getVersionNumber()
+ {
+ return $this->getFirstAttribute($this->schema->versionNumber());
+ }
+
+ /**
+ * Returns the print rate.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679405(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPrintRate()
+ {
+ return $this->getFirstAttribute($this->schema->printerPrintRate());
+ }
+
+ /**
+ * Returns the print rate unit.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679406(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getPrintRateUnit()
+ {
+ return $this->getFirstAttribute($this->schema->printerPrintRateUnit());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/RootDse.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/RootDse.php
new file mode 100644
index 0000000..31156c1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/RootDse.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Adldap\Models;
+
+use DateTime;
+
+/**
+ * Class RootDse.
+ *
+ * Represents the LDAP connections Root DSE record.
+ */
+class RootDse extends Model
+{
+ /**
+ * Returns the hosts current time in unix timestamp format.
+ *
+ * @return int
+ */
+ public function getCurrentTime()
+ {
+ $time = $this->getFirstAttribute($this->schema->currentTime());
+
+ return DateTime::createFromFormat($this->timestampFormat, $time)->getTimestamp();
+ }
+
+ /**
+ * Returns the hosts current time in the models date format.
+ *
+ * @return string
+ */
+ public function getCurrentTimeDate()
+ {
+ return (new DateTime())->setTimestamp($this->getCurrentTime())->format($this->dateFormat);
+ }
+
+ /**
+ * Returns the hosts configuration naming context.
+ *
+ * @return string
+ */
+ public function getConfigurationNamingContext()
+ {
+ return $this->getFirstAttribute($this->schema->configurationNamingContext());
+ }
+
+ /**
+ * Returns the hosts schema naming context.
+ *
+ * @return string
+ */
+ public function getSchemaNamingContext()
+ {
+ return $this->getFirstAttribute($this->schema->schemaNamingContext());
+ }
+
+ /**
+ * Returns the hosts DNS name.
+ *
+ * @return string
+ */
+ public function getDnsHostName()
+ {
+ return $this->getFirstAttribute($this->schema->dnsHostName());
+ }
+
+ /**
+ * Returns the current hosts server name.
+ *
+ * @return string
+ */
+ public function getServerName()
+ {
+ return $this->getFirstAttribute($this->schema->serverName());
+ }
+
+ /**
+ * Returns the DN of the root domain NC for this DC's forest.
+ *
+ * @return mixed
+ */
+ public function getRootDomainNamingContext()
+ {
+ return $this->getFirstAttribute($this->schema->rootDomainNamingContext());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/User.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/User.php
new file mode 100644
index 0000000..14c3343
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/User.php
@@ -0,0 +1,1054 @@
+<?php
+
+namespace Adldap\Models;
+
+use DateTime;
+use Adldap\Utilities;
+use Adldap\AdldapException;
+use Adldap\Schemas\ActiveDirectory;
+use Adldap\Models\Attributes\AccountControl;
+use Adldap\Models\Attributes\TSPropertyArray;
+use Illuminate\Contracts\Auth\Authenticatable;
+
+/**
+ * Class User.
+ *
+ * Represents an LDAP user.
+ */
+class User extends Entry implements Authenticatable
+{
+ use Concerns\HasUserProperties;
+ use Concerns\HasDescription;
+ use Concerns\HasMemberOf;
+ use Concerns\HasLastLogonAndLogOff;
+ use Concerns\HasUserAccountControl;
+
+ /** @var callable|null */
+ private static $passwordStrategy;
+
+ /**
+ * Password will be processed using given callback before saving.
+ *
+ * @param callable $strategy
+ */
+ public static function usePasswordStrategy(callable $strategy)
+ {
+ static::$passwordStrategy = $strategy;
+ }
+
+ /**
+ * Will return user set password strategy or default one.
+ *
+ * @return callable
+ */
+ public static function getPasswordStrategy(): callable
+ {
+ return static::$passwordStrategy ?? function ($password) {
+ return Utilities::encodePassword($password);
+ };
+ }
+
+ /**
+ * Get the name of the unique identifier for the user.
+ *
+ * @return string
+ */
+ public function getAuthIdentifierName()
+ {
+ return $this->schema->objectGuid();
+ }
+
+ /**
+ * Get the unique identifier for the user.
+ *
+ * @return mixed
+ */
+ public function getAuthIdentifier()
+ {
+ return $this->getConvertedGuid();
+ }
+
+ /**
+ * Get the password for the user.
+ *
+ * @return string
+ */
+ public function getAuthPassword()
+ {
+ }
+
+ /**
+ * Get the token value for the "remember me" session.
+ *
+ * @return string
+ */
+ public function getRememberToken()
+ {
+ }
+
+ /**
+ * Set the token value for the "remember me" session.
+ *
+ * @param string $value
+ *
+ * @return void
+ */
+ public function setRememberToken($value)
+ {
+ }
+
+ /**
+ * Get the column name for the "remember me" token.
+ *
+ * @return string
+ */
+ public function getRememberTokenName()
+ {
+ }
+
+ /**
+ * Returns the department number.
+ *
+ * @return string
+ */
+ public function getDepartmentNumber()
+ {
+ return $this->getFirstAttribute($this->schema->departmentNumber());
+ }
+
+ /**
+ * Sets the department number.
+ *
+ * @param string $number
+ *
+ * @return $this
+ */
+ public function setDepartmentNumber($number)
+ {
+ return $this->setFirstAttribute($this->schema->departmentNumber(), $number);
+ }
+
+ /**
+ * Returns the users info.
+ *
+ * @return mixed
+ */
+ public function getInfo()
+ {
+ return $this->getFirstAttribute($this->schema->info());
+ }
+
+ /**
+ * Sets the users info.
+ *
+ * @param string $info
+ *
+ * @return $this
+ */
+ public function setInfo($info)
+ {
+ return $this->setFirstAttribute($this->schema->info(), $info);
+ }
+
+ /**
+ * Returns the users physical delivery office name.
+ *
+ * @return string
+ */
+ public function getPhysicalDeliveryOfficeName()
+ {
+ return $this->getFirstAttribute($this->schema->physicalDeliveryOfficeName());
+ }
+
+ /**
+ * Sets the users physical delivery office name.
+ *
+ * @param string $deliveryOffice
+ *
+ * @return $this
+ */
+ public function setPhysicalDeliveryOfficeName($deliveryOffice)
+ {
+ return $this->setFirstAttribute($this->schema->physicalDeliveryOfficeName(), $deliveryOffice);
+ }
+
+ /**
+ * Returns the users locale.
+ *
+ * @return string
+ */
+ public function getLocale()
+ {
+ return $this->getFirstAttribute($this->schema->locale());
+ }
+
+ /**
+ * Sets the users locale.
+ *
+ * @param string $locale
+ *
+ * @return $this
+ */
+ public function setLocale($locale)
+ {
+ return $this->setFirstAttribute($this->schema->locale(), $locale);
+ }
+
+ /**
+ * Returns the users company.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675457(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getCompany()
+ {
+ return $this->getFirstAttribute($this->schema->company());
+ }
+
+ /**
+ * Sets the users company.
+ *
+ * @param string $company
+ *
+ * @return $this
+ */
+ public function setCompany($company)
+ {
+ return $this->setFirstAttribute($this->schema->company(), $company);
+ }
+
+ /**
+ * Returns the users mailbox store DN.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/aa487565(v=exchg.65).aspx
+ *
+ * @return string
+ */
+ public function getHomeMdb()
+ {
+ return $this->getFirstAttribute($this->schema->homeMdb());
+ }
+
+ /**
+ * Sets the users home drive.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676191(v=vs.85).aspx
+ *
+ * @return $this
+ */
+ public function setHomeDrive($drive)
+ {
+ return $this->setAttribute($this->schema->homeDrive(), $drive);
+ }
+
+ /**
+ * Specifies the drive letter to which to map the UNC path specified by homeDirectory.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676191(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getHomeDrive()
+ {
+ return $this->getFirstAttribute($this->schema->homeDrive());
+ }
+
+ /**
+ * Sets the users home directory.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676190(v=vs.85).aspx
+ *
+ * @param string $directory
+ *
+ * @return $this
+ */
+ public function setHomeDirectory($directory)
+ {
+ return $this->setAttribute($this->schema->homeDirectory(), $directory);
+ }
+
+ /**
+ * The home directory for the account.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676190(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getHomeDirectory()
+ {
+ return $this->getFirstAttribute($this->schema->homeDirectory());
+ }
+
+ /**
+ * The user's main home phone number.
+ *
+ * @link https://docs.microsoft.com/en-us/windows/desktop/ADSchema/a-homephone
+ *
+ * @return string|null
+ */
+ public function getHomePhone()
+ {
+ return $this->getFirstAttribute($this->schema->homePhone());
+ }
+
+ /**
+ * Returns the users principal name.
+ *
+ * This is usually their email address.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680857(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getUserPrincipalName()
+ {
+ return $this->getFirstAttribute($this->schema->userPrincipalName());
+ }
+
+ /**
+ * Sets the users user principal name.
+ *
+ * @param string $userPrincipalName
+ *
+ * @return $this
+ */
+ public function setUserPrincipalName($userPrincipalName)
+ {
+ return $this->setFirstAttribute($this->schema->userPrincipalName(), $userPrincipalName);
+ }
+
+ /**
+ * Returns an array of workstations the user is assigned to.
+ *
+ * @return array
+ */
+ public function getUserWorkstations()
+ {
+ $workstations = $this->getFirstAttribute($this->schema->userWorkstations());
+
+ return array_filter(explode(',', $workstations));
+ }
+
+ /**
+ * Sets the workstations the user can login to.
+ *
+ * @param string|array $workstations The names of the workstations the user can login to.
+ * Must be an array of names, or a comma separated
+ * list of names.
+ *
+ * @return $this
+ */
+ public function setUserWorkstations($workstations = [])
+ {
+ if (is_array($workstations)) {
+ $workstations = implode(',', $workstations);
+ }
+
+ return $this->setFirstAttribute($this->schema->userWorkstations(), $workstations);
+ }
+
+ /**
+ * Returns the users script path if the user has one.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679656(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getScriptPath()
+ {
+ return $this->getFirstAttribute($this->schema->scriptPath());
+ }
+
+ /**
+ * Sets the users script path.
+ *
+ * @param string $path
+ *
+ * @return $this
+ */
+ public function setScriptPath($path)
+ {
+ return $this->setFirstAttribute($this->schema->scriptPath(), $path);
+ }
+
+ /**
+ * Returns the users bad password count.
+ *
+ * @return string
+ */
+ public function getBadPasswordCount()
+ {
+ return $this->getFirstAttribute($this->schema->badPasswordCount());
+ }
+
+ /**
+ * Returns the users bad password time.
+ *
+ * @return string
+ */
+ public function getBadPasswordTime()
+ {
+ return $this->getFirstAttribute($this->schema->badPasswordTime());
+ }
+
+ /**
+ * Returns the bad password time unix timestamp.
+ *
+ * @return float|null
+ */
+ public function getBadPasswordTimestamp()
+ {
+ if ($time = $this->getBadPasswordTime()) {
+ return Utilities::convertWindowsTimeToUnixTime($time);
+ }
+ }
+
+ /**
+ * Returns the formatted timestamp of the bad password date.
+ *
+ * @throws \Exception
+ *
+ * @return string|null
+ */
+ public function getBadPasswordDate()
+ {
+ if ($timestamp = $this->getBadPasswordTimestamp()) {
+ return (new DateTime())->setTimestamp($timestamp)->format($this->dateFormat);
+ }
+ }
+
+ /**
+ * Returns the time when the users password was set last.
+ *
+ * @return string
+ */
+ public function getPasswordLastSet()
+ {
+ return $this->getFirstAttribute($this->schema->passwordLastSet());
+ }
+
+ /**
+ * Returns the password last set unix timestamp.
+ *
+ * @return float|null
+ */
+ public function getPasswordLastSetTimestamp()
+ {
+ if ($time = $this->getPasswordLastSet()) {
+ return Utilities::convertWindowsTimeToUnixTime($time);
+ }
+ }
+
+ /**
+ * Returns the formatted timestamp of the password last set date.
+ *
+ * @throws \Exception
+ *
+ * @return string|null
+ */
+ public function getPasswordLastSetDate()
+ {
+ if ($timestamp = $this->getPasswordLastSetTimestamp()) {
+ return (new DateTime())->setTimestamp($timestamp)->format($this->dateFormat);
+ }
+ }
+
+ /**
+ * Returns the users lockout time.
+ *
+ * @return string
+ */
+ public function getLockoutTime()
+ {
+ return $this->getFirstAttribute($this->schema->lockoutTime());
+ }
+
+ /**
+ * Returns the users lockout unix timestamp.
+ *
+ * @return float|null
+ */
+ public function getLockoutTimestamp()
+ {
+ if ($time = $this->getLockoutTime()) {
+ return Utilities::convertWindowsTimeToUnixTime($time);
+ }
+ }
+
+ /**
+ * Returns the formatted timestamp of the lockout date.
+ *
+ * @throws \Exception
+ *
+ * @return string|null
+ */
+ public function getLockoutDate()
+ {
+ if ($timestamp = $this->getLockoutTimestamp()) {
+ return (new DateTime())->setTimestamp($timestamp)->format($this->dateFormat);
+ }
+ }
+
+ /**
+ * Clears the accounts lockout time, unlocking the account.
+ *
+ * @return $this
+ */
+ public function setClearLockoutTime()
+ {
+ return $this->setFirstAttribute($this->schema->lockoutTime(), 0);
+ }
+
+ /**
+ * Returns the users profile file path.
+ *
+ * @return string
+ */
+ public function getProfilePath()
+ {
+ return $this->getFirstAttribute($this->schema->profilePath());
+ }
+
+ /**
+ * Sets the users profile path.
+ *
+ * @param string $path
+ *
+ * @return $this
+ */
+ public function setProfilePath($path)
+ {
+ return $this->setFirstAttribute($this->schema->profilePath(), $path);
+ }
+
+ /**
+ * Returns the users legacy exchange distinguished name.
+ *
+ * @return string
+ */
+ public function getLegacyExchangeDn()
+ {
+ return $this->getFirstAttribute($this->schema->legacyExchangeDn());
+ }
+
+ /**
+ * Sets the users account expiry date.
+ *
+ * If no expiry time is given, the account is set to never expire.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675098(v=vs.85).aspx
+ *
+ * @param float $expiryTime
+ *
+ * @return $this
+ */
+ public function setAccountExpiry($expiryTime)
+ {
+ $time = is_null($expiryTime) ? '9223372036854775807' : (string) Utilities::convertUnixTimeToWindowsTime($expiryTime);
+
+ return $this->setFirstAttribute($this->schema->accountExpires(), $time);
+ }
+
+ /**
+ * Returns an array of address book DNs
+ * that the user is listed to be shown in.
+ *
+ * @return array
+ */
+ public function getShowInAddressBook()
+ {
+ return $this->getAttribute($this->schema->showInAddressBook());
+ }
+
+ /**
+ * Returns the users thumbnail photo base 64 encoded.
+ *
+ * Suitable for inserting into an HTML image element.
+ *
+ * @return string|null
+ */
+ public function getThumbnailEncoded()
+ {
+ if ($data = base64_decode($this->getThumbnail(), $strict = true)) {
+ // In case we don't have the file info extension enabled,
+ // we'll set the jpeg mime type as default.
+ $mime = 'image/jpeg';
+
+ $image = base64_encode($data);
+
+ if (function_exists('finfo_open')) {
+ $finfo = finfo_open();
+
+ $mime = finfo_buffer($finfo, $data, FILEINFO_MIME_TYPE);
+
+ return "data:$mime;base64,$image";
+ }
+
+ return "data:$mime;base64,$image";
+ }
+ }
+
+ /**
+ * Returns the users thumbnail photo.
+ *
+ * @return mixed
+ */
+ public function getThumbnail()
+ {
+ return $this->getFirstAttribute($this->schema->thumbnail());
+ }
+
+ /**
+ * Sets the users thumbnail photo.
+ *
+ * @param string $data
+ * @param bool $encode
+ *
+ * @return $this
+ */
+ public function setThumbnail($data, $encode = true)
+ {
+ if ($encode && !base64_decode($data, $strict = true)) {
+ // If the string we're given is not base 64 encoded, then
+ // we will encode it before setting it on the user.
+ $data = base64_encode($data);
+ }
+
+ return $this->setAttribute($this->schema->thumbnail(), $data);
+ }
+
+ /**
+ * Returns the users JPEG photo.
+ *
+ * @return null|string
+ */
+ public function getJpegPhotoEncoded()
+ {
+ $jpeg = $this->getJpegPhoto();
+
+ return is_null($jpeg) ? $jpeg : 'data:image/jpeg;base64,'.base64_encode($jpeg);
+ }
+
+ /**
+ * Returns the users JPEG photo.
+ *
+ * @return mixed
+ */
+ public function getJpegPhoto()
+ {
+ return $this->getFirstAttribute($this->schema->jpegPhoto());
+ }
+
+ /**
+ * Sets the users JPEG photo.
+ *
+ * @param string $string
+ *
+ * @return $this
+ */
+ public function setJpegPhoto($string)
+ {
+ if (!base64_decode($string, $strict = true)) {
+ $string = base64_encode($string);
+ }
+
+ return $this->setAttribute($this->schema->jpegPhoto(), $string);
+ }
+
+ /**
+ * Return the employee ID.
+ *
+ * @return string
+ */
+ public function getEmployeeId()
+ {
+ return $this->getFirstAttribute($this->schema->employeeId());
+ }
+
+ /**
+ * Sets the employee ID.
+ *
+ * @param string $employeeId
+ *
+ * @return $this
+ */
+ public function setEmployeeId($employeeId)
+ {
+ return $this->setFirstAttribute($this->schema->employeeId(), $employeeId);
+ }
+
+ /**
+ * Returns the employee type.
+ *
+ * @return string|null
+ */
+ public function getEmployeeType()
+ {
+ return $this->getFirstAttribute($this->schema->employeeType());
+ }
+
+ /**
+ * Sets the employee type.
+ *
+ * @param string $type
+ *
+ * @return $this
+ */
+ public function setEmployeeType($type)
+ {
+ return $this->setFirstAttribute($this->schema->employeeType(), $type);
+ }
+
+ /**
+ * Returns the employee number.
+ *
+ * @return string
+ */
+ public function getEmployeeNumber()
+ {
+ return $this->getFirstAttribute($this->schema->employeeNumber());
+ }
+
+ /**
+ * Sets the employee number.
+ *
+ * @param string $number
+ *
+ * @return $this
+ */
+ public function setEmployeeNumber($number)
+ {
+ return $this->setFirstAttribute($this->schema->employeeNumber(), $number);
+ }
+
+ /**
+ * Returns the room number.
+ *
+ * @return string
+ */
+ public function getRoomNumber()
+ {
+ return $this->getFirstAttribute($this->schema->roomNumber());
+ }
+
+ /**
+ * Sets the room number.
+ *
+ * @param string $number
+ *
+ * @return $this
+ */
+ public function setRoomNumber($number)
+ {
+ return $this->setFirstAttribute($this->schema->roomNumber(), $number);
+ }
+
+ /**
+ * Return the personal title.
+ *
+ * @return $this
+ */
+ public function getPersonalTitle()
+ {
+ return $this->getFirstAttribute($this->schema->personalTitle());
+ }
+
+ /**
+ * Sets the personal title.
+ *
+ * @param string $personalTitle
+ *
+ * @return $this
+ */
+ public function setPersonalTitle($personalTitle)
+ {
+ return $this->setFirstAttribute($this->schema->personalTitle(), $personalTitle);
+ }
+
+ /**
+ * Return the user parameters.
+ *
+ * @return TSPropertyArray
+ */
+ public function getUserParameters()
+ {
+ return new TSPropertyArray($this->getFirstAttribute('userparameters'));
+ }
+
+ /**
+ * Sets the user parameters.
+ *
+ * @param TSPropertyArray $userParameters
+ *
+ * @return $this
+ */
+ public function setUserParameters(TSPropertyArray $userParameters)
+ {
+ return $this->setFirstAttribute('userparameters', $userParameters->toBinary());
+ }
+
+ /**
+ * Retrieves the primary group of the current user.
+ *
+ * @return Model|bool
+ */
+ public function getPrimaryGroup()
+ {
+ $groupSid = preg_replace('/\d+$/', $this->getPrimaryGroupId(), $this->getConvertedSid());
+
+ return $this->query->newInstance()->findBySid($groupSid);
+ }
+
+ /**
+ * Sets the password on the current user.
+ *
+ * @param string $password
+ *
+ * @throws AdldapException When no SSL or TLS secured connection is present.
+ *
+ * @return $this
+ */
+ public function setPassword($password)
+ {
+ $this->validateSecureConnection();
+
+ $encodedPassword = call_user_func(static::getPasswordStrategy(), $password);
+
+ if ($this->exists) {
+ // If the record exists, we need to add a batch replace
+ // modification, otherwise we'll receive a "type or
+ // value" exists exception from our LDAP server.
+ return $this->addModification(
+ $this->newBatchModification(
+ $this->schema->unicodePassword(),
+ LDAP_MODIFY_BATCH_REPLACE,
+ [$encodedPassword]
+ )
+ );
+ } else {
+ // Otherwise, we are creating a new record
+ // and we can set the attribute normally.
+ return $this->setFirstAttribute(
+ $this->schema->unicodePassword(),
+ $encodedPassword
+ );
+ }
+ }
+
+ /**
+ * Sets the option to force the password change at the next logon.
+ *
+ * Does not work if the "Password never expires" option is enabled.
+ *
+ * @return $this
+ */
+ public function setEnableForcePasswordChange()
+ {
+ return $this->setFirstAttribute($this->schema->passwordLastSet(), 0);
+ }
+
+ /**
+ * Sets the option to disable forcing a password change at the next logon.
+ *
+ * @return $this
+ */
+ public function setDisableForcePasswordChange()
+ {
+ return $this->setFirstAttribute($this->schema->passwordLastSet(), -1);
+ }
+
+ /**
+ * Change the password of the current user. This must be performed over SSL / TLS.
+ *
+ * Throws an exception on failure.
+ *
+ * @param string $oldPassword The new password
+ * @param string $newPassword The old password
+ * @param bool $replaceNotRemove Alternative password change method. Set to true if you're receiving 'CONSTRAINT'
+ * errors.
+ *
+ * @throws UserPasswordPolicyException When the new password does not match your password policy.
+ * @throws UserPasswordIncorrectException When the old password is incorrect.
+ * @throws AdldapException When an unknown cause of failure occurs.
+ *
+ * @return true
+ */
+ public function changePassword($oldPassword, $newPassword, $replaceNotRemove = false)
+ {
+ $this->validateSecureConnection();
+
+ $attribute = $this->schema->unicodePassword();
+
+ $modifications = [];
+
+ if ($replaceNotRemove) {
+ $modifications[] = $this->newBatchModification(
+ $attribute,
+ LDAP_MODIFY_BATCH_REPLACE,
+ [call_user_func(static::getPasswordStrategy(), $newPassword)]
+ );
+ } else {
+ // Create batch modification for removing the old password.
+ $modifications[] = $this->newBatchModification(
+ $attribute,
+ LDAP_MODIFY_BATCH_REMOVE,
+ [call_user_func(static::getPasswordStrategy(), $oldPassword)]
+ );
+
+ // Create batch modification for adding the new password.
+ $modifications[] = $this->newBatchModification(
+ $attribute,
+ LDAP_MODIFY_BATCH_ADD,
+ [call_user_func(static::getPasswordStrategy(), $newPassword)]
+ );
+ }
+
+ // Add the modifications.
+ foreach ($modifications as $modification) {
+ $this->addModification($modification);
+ }
+
+ $result = @$this->update();
+
+ if (!$result) {
+ // If the user failed to update, we'll see if we can
+ // figure out why by retrieving the extended error.
+ $error = $this->query->getConnection()->getExtendedError();
+ $code = $this->query->getConnection()->getExtendedErrorCode();
+
+ switch ($code) {
+ case '0000052D':
+ throw new UserPasswordPolicyException(
+ "Error: $code. Your new password does not match the password policy."
+ );
+ case '00000056':
+ throw new UserPasswordIncorrectException(
+ "Error: $code. Your old password is incorrect."
+ );
+ default:
+ throw new AdldapException($error);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Return true / false if LDAP User is active (enabled & not expired).
+ *
+ * @return bool
+ */
+ public function isActive()
+ {
+ return $this->isEnabled() && !$this->isExpired();
+ }
+
+ /**
+ * Return true / false if the LDAP User is expired.
+ *
+ * @param DateTime $date Optional date
+ *
+ * @return bool
+ */
+ public function isExpired(DateTime $date = null)
+ {
+ // Here we'll determine if the account expires by checking is expiration date.
+ if ($expirationDate = $this->expirationDate()) {
+ $date = $date ?: new DateTime();
+
+ return $expirationDate <= $date;
+ }
+
+ // The account has no expiry date.
+ return false;
+ }
+
+ /**
+ * Return the expiration date of the user account.
+ *
+ * @throws \Exception
+ *
+ * @return DateTime|null
+ */
+ public function expirationDate()
+ {
+ $accountExpiry = $this->getAccountExpiry();
+
+ // If the account expiry is zero or the expiry is equal to
+ // ActiveDirectory's 'never expire' value,
+ // then we'll return null here.
+ if ($accountExpiry == 0 || $accountExpiry == $this->getSchema()->neverExpiresDate()) {
+ return;
+ }
+
+ $unixTime = Utilities::convertWindowsTimeToUnixTime($accountExpiry);
+
+ return (new DateTime())->setTimestamp($unixTime);
+ }
+
+ /**
+ * Returns the users account expiry date.
+ *
+ * @return string
+ */
+ public function getAccountExpiry()
+ {
+ return $this->getFirstAttribute($this->schema->accountExpires());
+ }
+
+ /**
+ * Returns true / false if the users password is expired.
+ *
+ * @return bool
+ */
+ public function passwordExpired()
+ {
+ // First we'll check the users userAccountControl to see if
+ // it contains the 'password does not expire' flag.
+ if ($this->getUserAccountControlObject()->has(AccountControl::DONT_EXPIRE_PASSWORD)) {
+ return false;
+ }
+
+ $lastSet = (int) $this->getPasswordLastSet();
+
+ if ($lastSet === 0) {
+ // If the users last set time is zero, the password has
+ // been manually expired by an administrator.
+ return true;
+ }
+
+ // We'll check if we're using the ActiveDirectory schema to retrieve
+ // the max password age, as this is an AD-only feature.
+ if ($this->schema instanceof ActiveDirectory) {
+ $query = $this->query->newInstance();
+
+ // We need to get the root domain object to be able to
+ // retrieve the max password age on the domain.
+ $rootDomainObject = $query->select($this->schema->maxPasswordAge())
+ ->whereHas($this->schema->objectClass())
+ ->first();
+
+ $maxPasswordAge = $rootDomainObject->getMaxPasswordAge();
+
+ if (empty($maxPasswordAge)) {
+ // There is not a max password age set on the LDAP server.
+ return false;
+ }
+
+ // convert from 100 nanosecond ticks to seconds
+ $maxPasswordAgeSeconds = $maxPasswordAge / 10000000;
+
+ $lastSetUnixEpoch = Utilities::convertWindowsTimeToUnixTime($lastSet);
+ $passwordExpiryTime = $lastSetUnixEpoch - $maxPasswordAgeSeconds;
+
+ $expiresAt = (new DateTime())->setTimestamp($passwordExpiryTime);
+
+ // If our current time is greater than the users password
+ // expiry time, the users password has expired.
+ return (new DateTime())->getTimestamp() >= $expiresAt->getTimestamp();
+ }
+
+ return false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/UserPasswordIncorrectException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/UserPasswordIncorrectException.php
new file mode 100644
index 0000000..44cb39b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/UserPasswordIncorrectException.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace Adldap\Models;
+
+use Adldap\AdldapException;
+
+/**
+ * Class UserPasswordIncorrectException.
+ *
+ * Thrown when a users password is being changed
+ * and their current password given is incorrect.
+ */
+class UserPasswordIncorrectException extends AdldapException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/UserPasswordPolicyException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/UserPasswordPolicyException.php
new file mode 100644
index 0000000..9a99faa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Models/UserPasswordPolicyException.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace Adldap\Models;
+
+use Adldap\AdldapException;
+
+/**
+ * Class UserPasswordPolicyException.
+ *
+ * Thrown when a users password is being changed but their new password
+ * does not conform to the LDAP servers password policy.
+ */
+class UserPasswordPolicyException extends AdldapException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Builder.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Builder.php
new file mode 100644
index 0000000..48f253f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Builder.php
@@ -0,0 +1,1956 @@
+<?php
+
+namespace Adldap\Query;
+
+use Closure;
+use Adldap\Adldap;
+use Adldap\Utilities;
+use Adldap\Models\Model;
+use Illuminate\Support\Arr;
+use InvalidArgumentException;
+use Adldap\Schemas\ActiveDirectory;
+use Adldap\Schemas\SchemaInterface;
+use Adldap\Query\Events\QueryExecuted;
+use Adldap\Models\ModelNotFoundException;
+use Adldap\Connections\ConnectionInterface;
+
+class Builder
+{
+ /**
+ * The selected columns to retrieve on the query.
+ *
+ * @var array
+ */
+ public $columns = ['*'];
+
+ /**
+ * The query filters.
+ *
+ * @var array
+ */
+ public $filters = [
+ 'and' => [],
+ 'or' => [],
+ 'raw' => [],
+ ];
+
+ /**
+ * The size limit of the query.
+ *
+ * @var int
+ */
+ public $limit = 0;
+
+ /**
+ * Determines whether the current query is paginated.
+ *
+ * @var bool
+ */
+ public $paginated = false;
+
+ /**
+ * The field to sort search results by.
+ *
+ * @var string
+ */
+ protected $sortByField = '';
+
+ /**
+ * The direction to sort the results by.
+ *
+ * @var string
+ */
+ protected $sortByDirection = '';
+
+ /**
+ * The sort flags for sorting query results.
+ *
+ * @var int
+ */
+ protected $sortByFlags;
+
+ /**
+ * The distinguished name to perform searches upon.
+ *
+ * @var string|null
+ */
+ protected $dn;
+
+ /**
+ * The default query type.
+ *
+ * @var string
+ */
+ protected $type = 'search';
+
+ /**
+ * Determines whether or not to return LDAP results in their raw array format.
+ *
+ * @var bool
+ */
+ protected $raw = false;
+
+ /**
+ * Determines whether the query is nested.
+ *
+ * @var bool
+ */
+ protected $nested = false;
+
+ /**
+ * Determines whether the query should be cached.
+ *
+ * @var bool
+ */
+ protected $caching = false;
+
+ /**
+ * How long the query should be cached until.
+ *
+ * @var \DateTimeInterface|null
+ */
+ protected $cacheUntil = null;
+
+ /**
+ * Determines whether the query cache must be flushed.
+ *
+ * @var bool
+ */
+ protected $flushCache = false;
+
+ /**
+ * The current connection instance.
+ *
+ * @var ConnectionInterface
+ */
+ protected $connection;
+
+ /**
+ * The current grammar instance.
+ *
+ * @var Grammar
+ */
+ protected $grammar;
+
+ /**
+ * The current schema instance.
+ *
+ * @var SchemaInterface
+ */
+ protected $schema;
+
+ /**
+ * The current cache instance.
+ *
+ * @var Cache|null
+ */
+ protected $cache;
+
+ /**
+ * Constructor.
+ *
+ * @param ConnectionInterface $connection
+ * @param Grammar|null $grammar
+ * @param SchemaInterface|null $schema
+ */
+ public function __construct(ConnectionInterface $connection, Grammar $grammar = null, SchemaInterface $schema = null)
+ {
+ $this->setConnection($connection)
+ ->setGrammar($grammar)
+ ->setSchema($schema);
+ }
+
+ /**
+ * Sets the current connection.
+ *
+ * @param ConnectionInterface $connection
+ *
+ * @return Builder
+ */
+ public function setConnection(ConnectionInterface $connection)
+ {
+ $this->connection = $connection;
+
+ return $this;
+ }
+
+ /**
+ * Sets the current filter grammar.
+ *
+ * @param Grammar|null $grammar
+ *
+ * @return Builder
+ */
+ public function setGrammar(Grammar $grammar = null)
+ {
+ $this->grammar = $grammar ?: new Grammar();
+
+ return $this;
+ }
+
+ /**
+ * Sets the current schema.
+ *
+ * @param SchemaInterface|null $schema
+ *
+ * @return Builder
+ */
+ public function setSchema(SchemaInterface $schema = null)
+ {
+ $this->schema = $schema ?: new ActiveDirectory();
+
+ return $this;
+ }
+
+ /**
+ * Returns the current schema.
+ *
+ * @return SchemaInterface
+ */
+ public function getSchema()
+ {
+ return $this->schema;
+ }
+
+ /**
+ * Sets the cache to store query results.
+ *
+ * @param Cache|null $cache
+ */
+ public function setCache(Cache $cache = null)
+ {
+ $this->cache = $cache;
+
+ return $this;
+ }
+
+ /**
+ * Returns a new Query Builder instance.
+ *
+ * @param string $baseDn
+ *
+ * @return Builder
+ */
+ public function newInstance($baseDn = null)
+ {
+ // We'll set the base DN of the new Builder so
+ // developers don't need to do this manually.
+ $dn = is_null($baseDn) ? $this->getDn() : $baseDn;
+
+ return (new static($this->connection, $this->grammar, $this->schema))
+ ->setDn($dn);
+ }
+
+ /**
+ * Returns a new nested Query Builder instance.
+ *
+ * @param Closure|null $closure
+ *
+ * @return $this
+ */
+ public function newNestedInstance(Closure $closure = null)
+ {
+ $query = $this->newInstance()->nested();
+
+ if ($closure) {
+ call_user_func($closure, $query);
+ }
+
+ return $query;
+ }
+
+ /**
+ * Returns the current query.
+ *
+ * @return Collection|array
+ */
+ public function get()
+ {
+ // We'll mute any warnings / errors here. We just need to
+ // know if any query results were returned.
+ return @$this->query($this->getQuery());
+ }
+
+ /**
+ * Compiles and returns the current query string.
+ *
+ * @return string
+ */
+ public function getQuery()
+ {
+ // We need to ensure we have at least one filter, as
+ // no query results will be returned otherwise.
+ if (count(array_filter($this->filters)) === 0) {
+ $this->whereHas($this->schema->objectClass());
+ }
+
+ return $this->grammar->compile($this);
+ }
+
+ /**
+ * Returns the unescaped query.
+ *
+ * @return string
+ */
+ public function getUnescapedQuery()
+ {
+ return Utilities::unescape($this->getQuery());
+ }
+
+ /**
+ * Returns the current Grammar instance.
+ *
+ * @return Grammar
+ */
+ public function getGrammar()
+ {
+ return $this->grammar;
+ }
+
+ /**
+ * Returns the current Connection instance.
+ *
+ * @return ConnectionInterface
+ */
+ public function getConnection()
+ {
+ return $this->connection;
+ }
+
+ /**
+ * Returns the builders DN to perform searches upon.
+ *
+ * @return string
+ */
+ public function getDn()
+ {
+ return $this->dn;
+ }
+
+ /**
+ * Sets the DN to perform searches upon.
+ *
+ * @param string|Model|null $dn
+ *
+ * @return Builder
+ */
+ public function setDn($dn = null)
+ {
+ $this->dn = $dn instanceof Model ? $dn->getDn() : $dn;
+
+ return $this;
+ }
+
+ /**
+ * Alias for setting the base DN of the query.
+ *
+ * @param string|Model|null $dn
+ *
+ * @return Builder
+ */
+ public function in($dn = null)
+ {
+ return $this->setDn($dn);
+ }
+
+ /**
+ * Sets the size limit of the current query.
+ *
+ * @param int $limit
+ *
+ * @return Builder
+ */
+ public function limit($limit = 0)
+ {
+ $this->limit = $limit;
+
+ return $this;
+ }
+
+ /**
+ * Performs the specified query on the current LDAP connection.
+ *
+ * @param string $query
+ *
+ * @return \Adldap\Query\Collection|array
+ */
+ public function query($query)
+ {
+ $start = microtime(true);
+
+ // Here we will create the execution callback. This allows us
+ // to only execute an LDAP request if caching is disabled
+ // or if no cache of the given query exists yet.
+ $callback = function () use ($query) {
+ return $this->parse($this->run($query));
+ };
+
+ // If caching is enabled and we have a cache instance available,
+ // we will try to retrieve the cached results instead.
+ // Otherwise, we will simply execute the callback.
+ if ($this->caching && $this->cache) {
+ $results = $this->getCachedResponse($this->getCacheKey($query), $callback);
+ } else {
+ $results = $callback();
+ }
+
+ // Log the query.
+ $this->logQuery($this, $this->type, $this->getElapsedTime($start));
+
+ // Process & return the results.
+ return $this->newProcessor()->process($results);
+ }
+
+ /**
+ * Paginates the current LDAP query.
+ *
+ * @param int $perPage
+ * @param int $currentPage
+ * @param bool $isCritical
+ *
+ * @return Paginator
+ */
+ public function paginate($perPage = 1000, $currentPage = 0, $isCritical = true)
+ {
+ $this->paginated = true;
+
+ $start = microtime(true);
+
+ $query = $this->getQuery();
+
+ // Here we will create the pagination callback. This allows us
+ // to only execute an LDAP request if caching is disabled
+ // or if no cache of the given query exists yet.
+ $callback = function () use ($query, $perPage, $isCritical) {
+ return $this->runPaginate($query, $perPage, $isCritical);
+ };
+
+ // If caching is enabled and we have a cache instance available,
+ // we will try to retrieve the cached results instead.
+ if ($this->caching && $this->cache) {
+ $pages = $this->getCachedResponse($this->getCacheKey($query), $callback);
+ } else {
+ $pages = $callback();
+ }
+
+ // Log the query.
+ $this->logQuery($this, 'paginate', $this->getElapsedTime($start));
+
+ // Process & return the results.
+ return $this->newProcessor()->processPaginated($pages, $perPage, $currentPage);
+ }
+
+ /**
+ * Get the cached response or execute and cache the callback value.
+ *
+ * @param string $key
+ * @param Closure $callback
+ *
+ * @return mixed
+ */
+ protected function getCachedResponse($key, Closure $callback)
+ {
+ if ($this->flushCache) {
+ $this->cache->delete($key);
+ }
+
+ return $this->cache->remember($key, $this->cacheUntil, $callback);
+ }
+
+ /**
+ * Runs the query operation with the given filter.
+ *
+ * @param string $filter
+ *
+ * @return resource
+ */
+ protected function run($filter)
+ {
+ return $this->connection->{$this->type}(
+ $this->getDn(),
+ $filter,
+ $this->getSelects(),
+ $onlyAttributes = false,
+ $this->limit
+ );
+ }
+
+ /**
+ * Runs the paginate operation with the given filter.
+ *
+ * @param string $filter
+ * @param int $perPage
+ * @param bool $isCritical
+ *
+ * @return array
+ */
+ protected function runPaginate($filter, $perPage, $isCritical)
+ {
+ return $this->connection->supportsServerControlsInMethods() ?
+ $this->compatiblePaginationCallback($filter, $perPage, $isCritical) :
+ $this->deprecatedPaginationCallback($filter, $perPage, $isCritical);
+ }
+
+ /**
+ * Create a deprecated pagination callback compatible with PHP 7.2.
+ *
+ * @param string $filter
+ * @param int $perPage
+ * @param bool $isCritical
+ *
+ * @return array
+ */
+ protected function deprecatedPaginationCallback($filter, $perPage, $isCritical)
+ {
+ $pages = [];
+
+ $cookie = '';
+
+ do {
+ $this->connection->controlPagedResult($perPage, $isCritical, $cookie);
+
+ if (! $resource = $this->run($filter)) {
+ break;
+ }
+
+ // If we have been given a valid resource, we will retrieve the next
+ // pagination cookie to send for our next pagination request.
+ $this->connection->controlPagedResultResponse($resource, $cookie);
+
+ $pages[] = $this->parse($resource);
+ } while (!empty($cookie));
+
+ // Reset paged result on the current connection. We won't pass in the current $perPage
+ // parameter since we want to reset the page size to the default '1000'. Sending '0'
+ // eliminates any further opportunity for running queries in the same request,
+ // even though that is supposed to be the correct usage.
+ $this->connection->controlPagedResult();
+
+ return $pages;
+ }
+
+ /**
+ * Create a compatible pagination callback compatible with PHP 7.3 and greater.
+ *
+ * @param string $filter
+ * @param int $perPage
+ * @param bool $isCritical
+ *
+ * @return array
+ */
+ protected function compatiblePaginationCallback($filter, $perPage, $isCritical)
+ {
+ $pages = [];
+
+ // Setup our paged results control.
+ $controls = [
+ LDAP_CONTROL_PAGEDRESULTS => [
+ 'oid' => LDAP_CONTROL_PAGEDRESULTS,
+ 'isCritical' => $isCritical,
+ 'value' => [
+ 'size' => $perPage,
+ 'cookie' => '',
+ ],
+ ],
+ ];
+
+ do {
+ // Update the server controls.
+ $this->connection->setOption(LDAP_OPT_SERVER_CONTROLS, $controls);
+
+ if (! $resource = $this->run($filter)) {
+ break;
+ }
+
+ $errorCode = $dn = $errorMessage = $refs = null;
+
+ // Update the server controls with the servers response.
+ $this->connection->parseResult($resource, $errorCode, $dn, $errorMessage, $refs, $controls);
+
+ $pages[] = $this->parse($resource);
+
+ // Reset paged result on the current connection. We won't pass in the current $perPage
+ // parameter since we want to reset the page size to the default '1000'. Sending '0'
+ // eliminates any further opportunity for running queries in the same request,
+ // even though that is supposed to be the correct usage.
+ $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['size'] = $perPage;
+ } while (!empty($controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']));
+
+ // After running the query, we will clear the LDAP server controls. This
+ // allows the controls to be automatically reset before each new query
+ // that is conducted on the same connection during each request.
+ $this->connection->setOption(LDAP_OPT_SERVER_CONTROLS, []);
+
+ return $pages;
+ }
+
+ /**
+ * Parses the given LDAP resource by retrieving its entries.
+ *
+ * @param resource $resource
+ *
+ * @return array
+ */
+ protected function parse($resource)
+ {
+ // Normalize entries. Get entries returns false on failure.
+ // We'll always want an array in this situation.
+ $entries = $this->connection->getEntries($resource) ?: [];
+
+ // Free up memory.
+ if (is_resource($resource)) {
+ $this->connection->freeResult($resource);
+ }
+
+ return $entries;
+ }
+
+ /**
+ * Returns the cache key.
+ *
+ * @param string $query
+ *
+ * @return string
+ */
+ protected function getCacheKey($query)
+ {
+ $key = $this->connection->getHost()
+ .$this->type
+ .$this->getDn()
+ .$query
+ .implode('', $this->getSelects())
+ .$this->limit
+ .$this->paginated;
+
+ return md5($key);
+ }
+
+ /**
+ * Returns the first entry in a search result.
+ *
+ * @param array|string $columns
+ *
+ * @return Model|array|null
+ */
+ public function first($columns = [])
+ {
+ $results = $this->select($columns)->limit(1)->get();
+
+ // Since results may be returned inside an array if `raw()`
+ // is specified, then we'll use our array helper
+ // to retrieve the first result.
+ return Arr::get($results, 0);
+ }
+
+ /**
+ * Returns the first entry in a search result.
+ *
+ * If no entry is found, an exception is thrown.
+ *
+ * @param array|string $columns
+ *
+ * @throws ModelNotFoundException
+ *
+ * @return Model|array
+ */
+ public function firstOrFail($columns = [])
+ {
+ $record = $this->first($columns);
+
+ if (!$record) {
+ throw (new ModelNotFoundException())
+ ->setQuery($this->getUnescapedQuery(), $this->getDn());
+ }
+
+ return $record;
+ }
+
+ /**
+ * Finds a record by the specified attribute and value.
+ *
+ * @param string $attribute
+ * @param string $value
+ * @param array|string $columns
+ *
+ * @return Model|array|false
+ */
+ public function findBy($attribute, $value, $columns = [])
+ {
+ try {
+ return $this->findByOrFail($attribute, $value, $columns);
+ } catch (ModelNotFoundException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Finds a record by the specified attribute and value.
+ *
+ * If no record is found an exception is thrown.
+ *
+ * @param string $attribute
+ * @param string $value
+ * @param array|string $columns
+ *
+ * @throws ModelNotFoundException
+ *
+ * @return Model|array
+ */
+ public function findByOrFail($attribute, $value, $columns = [])
+ {
+ return $this->whereEquals($attribute, $value)->firstOrFail($columns);
+ }
+
+ /**
+ * Finds a record using ambiguous name resolution.
+ *
+ * @param string|array $value
+ * @param array|string $columns
+ *
+ * @return Model|array|null
+ */
+ public function find($value, $columns = [])
+ {
+ if (is_array($value)) {
+ return $this->findMany($value, $columns);
+ }
+
+ // If we're not using ActiveDirectory, we can't use ANR. We'll make our own query.
+ if (!is_a($this->schema, ActiveDirectory::class)) {
+ return $this->prepareAnrEquivalentQuery($value)->first($columns);
+ }
+
+ return $this->findBy($this->schema->anr(), $value, $columns);
+ }
+
+ /**
+ * Finds multiple records using ambiguous name resolution.
+ *
+ * @param array $values
+ * @param array $columns
+ *
+ * @return \Adldap\Query\Collection|array
+ */
+ public function findMany(array $values = [], $columns = [])
+ {
+ $this->select($columns);
+
+ if (!is_a($this->schema, ActiveDirectory::class)) {
+ $query = $this;
+
+ foreach ($values as $value) {
+ $query->prepareAnrEquivalentQuery($value);
+ }
+
+ return $query->get();
+ }
+
+ return $this->findManyBy($this->schema->anr(), $values);
+ }
+
+ /**
+ * Creates an ANR equivalent query for LDAP distributions that do not support ANR.
+ *
+ * @param string $value
+ *
+ * @return Builder
+ */
+ protected function prepareAnrEquivalentQuery($value)
+ {
+ return $this->orFilter(function (self $query) use ($value) {
+ $locateBy = [
+ $this->schema->name(),
+ $this->schema->email(),
+ $this->schema->userId(),
+ $this->schema->lastName(),
+ $this->schema->firstName(),
+ $this->schema->commonName(),
+ $this->schema->displayName(),
+ ];
+
+ foreach ($locateBy as $attribute) {
+ $query->whereEquals($attribute, $value);
+ }
+ });
+ }
+
+ /**
+ * Finds many records by the specified attribute.
+ *
+ * @param string $attribute
+ * @param array $values
+ * @param array $columns
+ *
+ * @return \Adldap\Query\Collection|array
+ */
+ public function findManyBy($attribute, array $values = [], $columns = [])
+ {
+ $query = $this->select($columns);
+
+ foreach ($values as $value) {
+ $query->orWhere([$attribute => $value]);
+ }
+
+ return $query->get();
+ }
+
+ /**
+ * Finds a record using ambiguous name resolution.
+ *
+ * If a record is not found, an exception is thrown.
+ *
+ * @param string $value
+ * @param array|string $columns
+ *
+ * @throws ModelNotFoundException
+ *
+ * @return Model|array
+ */
+ public function findOrFail($value, $columns = [])
+ {
+ $entry = $this->find($value, $columns);
+
+ // Make sure we check if the result is an entry or an array before
+ // we throw an exception in case the user wants raw results.
+ if (!$entry instanceof Model && !is_array($entry)) {
+ throw (new ModelNotFoundException())
+ ->setQuery($this->getUnescapedQuery(), $this->getDn());
+ }
+
+ return $entry;
+ }
+
+ /**
+ * Finds a record by its distinguished name.
+ *
+ * @param string $dn
+ * @param array|string $columns
+ *
+ * @return bool|Model
+ */
+ public function findByDn($dn, $columns = [])
+ {
+ try {
+ return $this->findByDnOrFail($dn, $columns);
+ } catch (ModelNotFoundException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Finds a record by its distinguished name.
+ *
+ * Fails upon no records returned.
+ *
+ * @param string $dn
+ * @param array|string $columns
+ *
+ * @throws ModelNotFoundException
+ *
+ * @return Model|array
+ */
+ public function findByDnOrFail($dn, $columns = [])
+ {
+ // Since we're setting our base DN to be able to retrieve a model
+ // by its distinguished name, we need to set it back to
+ // our configured base so it is not overwritten.
+ $base = $this->getDn();
+
+ $model = $this->setDn($dn)
+ ->read()
+ ->whereHas($this->schema->objectClass())
+ ->firstOrFail($columns);
+
+ // Reset the models query builder (in case a model is returned).
+ // Otherwise, we must be requesting a raw result.
+ if ($model instanceof Model) {
+ $model->setQuery($this->in($base));
+ }
+
+ return $model;
+ }
+
+ /**
+ * Finds a record by its string GUID.
+ *
+ * @param string $guid
+ * @param array|string $columns
+ *
+ * @return Model|array|false
+ */
+ public function findByGuid($guid, $columns = [])
+ {
+ try {
+ return $this->findByGuidOrFail($guid, $columns);
+ } catch (ModelNotFoundException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Finds a record by its string GUID.
+ *
+ * Fails upon no records returned.
+ *
+ * @param string $guid
+ * @param array|string $columns
+ *
+ * @throws ModelNotFoundException
+ *
+ * @return Model|array
+ */
+ public function findByGuidOrFail($guid, $columns = [])
+ {
+ if ($this->schema->objectGuidRequiresConversion()) {
+ $guid = Utilities::stringGuidToHex($guid);
+ }
+
+ return $this->select($columns)->whereRaw([
+ $this->schema->objectGuid() => $guid,
+ ])->firstOrFail();
+ }
+
+ /**
+ * Finds a record by its Object SID.
+ *
+ * @param string $sid
+ * @param array|string $columns
+ *
+ * @return Model|array|false
+ */
+ public function findBySid($sid, $columns = [])
+ {
+ try {
+ return $this->findBySidOrFail($sid, $columns);
+ } catch (ModelNotFoundException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Finds a record by its Object SID.
+ *
+ * Fails upon no records returned.
+ *
+ * @param string $sid
+ * @param array|string $columns
+ *
+ * @throws ModelNotFoundException
+ *
+ * @return Model|array
+ */
+ public function findBySidOrFail($sid, $columns = [])
+ {
+ return $this->findByOrFail($this->schema->objectSid(), $sid, $columns);
+ }
+
+ /**
+ * Finds the Base DN of your domain controller.
+ *
+ * @return string|bool
+ */
+ public function findBaseDn()
+ {
+ $result = $this->setDn(null)
+ ->read()
+ ->raw()
+ ->whereHas($this->schema->objectClass())
+ ->first();
+
+ $key = $this->schema->defaultNamingContext();
+
+ if (is_array($result) && array_key_exists($key, $result)) {
+ if (array_key_exists(0, $result[$key])) {
+ return $result[$key][0];
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Adds the inserted fields to query on the current LDAP connection.
+ *
+ * @param array|string $columns
+ *
+ * @return Builder
+ */
+ public function select($columns = [])
+ {
+ $columns = is_array($columns) ? $columns : func_get_args();
+
+ if (!empty($columns)) {
+ $this->columns = $columns;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds a raw filter to the current query.
+ *
+ * @param array|string $filters
+ *
+ * @return Builder
+ */
+ public function rawFilter($filters = [])
+ {
+ $filters = is_array($filters) ? $filters : func_get_args();
+
+ foreach ($filters as $filter) {
+ $this->filters['raw'][] = $filter;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds a nested 'and' filter to the current query.
+ *
+ * @param Closure $closure
+ *
+ * @return Builder
+ */
+ public function andFilter(Closure $closure)
+ {
+ $query = $this->newNestedInstance($closure);
+
+ $filter = $this->grammar->compileAnd($query->getQuery());
+
+ return $this->rawFilter($filter);
+ }
+
+ /**
+ * Adds a nested 'or' filter to the current query.
+ *
+ * @param Closure $closure
+ *
+ * @return Builder
+ */
+ public function orFilter(Closure $closure)
+ {
+ $query = $this->newNestedInstance($closure);
+
+ $filter = $this->grammar->compileOr($query->getQuery());
+
+ return $this->rawFilter($filter);
+ }
+
+ /**
+ * Adds a nested 'not' filter to the current query.
+ *
+ * @param Closure $closure
+ *
+ * @return Builder
+ */
+ public function notFilter(Closure $closure)
+ {
+ $query = $this->newNestedInstance($closure);
+
+ $filter = $this->grammar->compileNot($query->getQuery());
+
+ return $this->rawFilter($filter);
+ }
+
+ /**
+ * Adds a where clause to the current query.
+ *
+ * @param string|array $field
+ * @param string $operator
+ * @param string $value
+ * @param string $boolean
+ * @param bool $raw
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return Builder
+ */
+ public function where($field, $operator = null, $value = null, $boolean = 'and', $raw = false)
+ {
+ if (is_array($field)) {
+ // If the column is an array, we will assume it is an array of
+ // key-value pairs and can add them each as a where clause.
+ return $this->addArrayOfWheres($field, $boolean, $raw);
+ }
+
+ // We'll bypass the 'has' and 'notHas' operator since they
+ // only require two arguments inside the where method.
+ $bypass = [Operator::$has, Operator::$notHas];
+
+ // Here we will make some assumptions about the operator. If only
+ // 2 values are passed to the method, we will assume that
+ // the operator is 'equals' and keep going.
+ if (func_num_args() === 2 && in_array($operator, $bypass) === false) {
+ list($value, $operator) = [$operator, '='];
+ }
+
+ if (!in_array($operator, Operator::all())) {
+ throw new InvalidArgumentException("Invalid where operator: {$operator}");
+ }
+
+ // We'll escape the value if raw isn't requested.
+ $value = $raw ? $value : $this->escape($value);
+
+ $field = $this->escape($field, $ignore = null, 3);
+
+ $this->addFilter($boolean, compact('field', 'operator', 'value'));
+
+ return $this;
+ }
+
+ /**
+ * Adds a raw where clause to the current query.
+ *
+ * Values given to this method are not escaped.
+ *
+ * @param string|array $field
+ * @param string $operator
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function whereRaw($field, $operator = null, $value = null)
+ {
+ return $this->where($field, $operator, $value, 'and', true);
+ }
+
+ /**
+ * Adds a 'where equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function whereEquals($field, $value)
+ {
+ return $this->where($field, Operator::$equals, $value);
+ }
+
+ /**
+ * Adds a 'where not equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function whereNotEquals($field, $value)
+ {
+ return $this->where($field, Operator::$doesNotEqual, $value);
+ }
+
+ /**
+ * Adds a 'where approximately equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function whereApproximatelyEquals($field, $value)
+ {
+ return $this->where($field, Operator::$approximatelyEquals, $value);
+ }
+
+ /**
+ * Adds a 'where has' clause to the current query.
+ *
+ * @param string $field
+ *
+ * @return Builder
+ */
+ public function whereHas($field)
+ {
+ return $this->where($field, Operator::$has);
+ }
+
+ /**
+ * Adds a 'where not has' clause to the current query.
+ *
+ * @param string $field
+ *
+ * @return Builder
+ */
+ public function whereNotHas($field)
+ {
+ return $this->where($field, Operator::$notHas);
+ }
+
+ /**
+ * Adds a 'where contains' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function whereContains($field, $value)
+ {
+ return $this->where($field, Operator::$contains, $value);
+ }
+
+ /**
+ * Adds a 'where contains' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function whereNotContains($field, $value)
+ {
+ return $this->where($field, Operator::$notContains, $value);
+ }
+
+ /**
+ * Query for entries that match any of the values provided for the given field.
+ *
+ * @param string $field
+ * @param array $values
+ *
+ * @return Builder
+ */
+ public function whereIn($field, array $values)
+ {
+ return $this->orFilter(function (self $query) use ($field, $values) {
+ foreach ($values as $value) {
+ $query->whereEquals($field, $value);
+ }
+ });
+ }
+
+ /**
+ * Adds a 'between' clause to the current query.
+ *
+ * @param string $field
+ * @param array $values
+ *
+ * @return Builder
+ */
+ public function whereBetween($field, array $values)
+ {
+ return $this->where([
+ [$field, '>=', $values[0]],
+ [$field, '<=', $values[1]],
+ ]);
+ }
+
+ /**
+ * Adds a 'where starts with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function whereStartsWith($field, $value)
+ {
+ return $this->where($field, Operator::$startsWith, $value);
+ }
+
+ /**
+ * Adds a 'where *not* starts with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function whereNotStartsWith($field, $value)
+ {
+ return $this->where($field, Operator::$notStartsWith, $value);
+ }
+
+ /**
+ * Adds a 'where ends with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function whereEndsWith($field, $value)
+ {
+ return $this->where($field, Operator::$endsWith, $value);
+ }
+
+ /**
+ * Adds a 'where *not* ends with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function whereNotEndsWith($field, $value)
+ {
+ return $this->where($field, Operator::$notEndsWith, $value);
+ }
+
+ /**
+ * Adds a enabled filter to the current query.
+ *
+ * @return Builder
+ */
+ public function whereEnabled()
+ {
+ return $this->rawFilter($this->schema->filterEnabled());
+ }
+
+ /**
+ * Adds a disabled filter to the current query.
+ *
+ * @return Builder
+ */
+ public function whereDisabled()
+ {
+ return $this->rawFilter($this->schema->filterDisabled());
+ }
+
+ /**
+ * Adds a 'member of' filter to the current query.
+ *
+ * @param string $dn
+ *
+ * @return Builder
+ */
+ public function whereMemberOf($dn)
+ {
+ return $this->whereEquals($this->schema->memberOfRecursive(), $dn);
+ }
+
+ /**
+ * Adds an 'or where' clause to the current query.
+ *
+ * @param array|string $field
+ * @param string|null $operator
+ * @param string|null $value
+ *
+ * @return Builder
+ */
+ public function orWhere($field, $operator = null, $value = null)
+ {
+ return $this->where($field, $operator, $value, 'or');
+ }
+
+ /**
+ * Adds a raw or where clause to the current query.
+ *
+ * Values given to this method are not escaped.
+ *
+ * @param string $field
+ * @param string $operator
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function orWhereRaw($field, $operator = null, $value = null)
+ {
+ return $this->where($field, $operator, $value, 'or', true);
+ }
+
+ /**
+ * Adds an 'or where has' clause to the current query.
+ *
+ * @param string $field
+ *
+ * @return Builder
+ */
+ public function orWhereHas($field)
+ {
+ return $this->orWhere($field, Operator::$has);
+ }
+
+ /**
+ * Adds a 'where not has' clause to the current query.
+ *
+ * @param string $field
+ *
+ * @return Builder
+ */
+ public function orWhereNotHas($field)
+ {
+ return $this->orWhere($field, Operator::$notHas);
+ }
+
+ /**
+ * Adds an 'or where equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function orWhereEquals($field, $value)
+ {
+ return $this->orWhere($field, Operator::$equals, $value);
+ }
+
+ /**
+ * Adds an 'or where not equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function orWhereNotEquals($field, $value)
+ {
+ return $this->orWhere($field, Operator::$doesNotEqual, $value);
+ }
+
+ /**
+ * Adds a 'or where approximately equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function orWhereApproximatelyEquals($field, $value)
+ {
+ return $this->orWhere($field, Operator::$approximatelyEquals, $value);
+ }
+
+ /**
+ * Adds an 'or where contains' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function orWhereContains($field, $value)
+ {
+ return $this->orWhere($field, Operator::$contains, $value);
+ }
+
+ /**
+ * Adds an 'or where *not* contains' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function orWhereNotContains($field, $value)
+ {
+ return $this->orWhere($field, Operator::$notContains, $value);
+ }
+
+ /**
+ * Adds an 'or where starts with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function orWhereStartsWith($field, $value)
+ {
+ return $this->orWhere($field, Operator::$startsWith, $value);
+ }
+
+ /**
+ * Adds an 'or where *not* starts with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function orWhereNotStartsWith($field, $value)
+ {
+ return $this->orWhere($field, Operator::$notStartsWith, $value);
+ }
+
+ /**
+ * Adds an 'or where ends with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function orWhereEndsWith($field, $value)
+ {
+ return $this->orWhere($field, Operator::$endsWith, $value);
+ }
+
+ /**
+ * Adds an 'or where *not* ends with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return Builder
+ */
+ public function orWhereNotEndsWith($field, $value)
+ {
+ return $this->orWhere($field, Operator::$notEndsWith, $value);
+ }
+
+ /**
+ * Adds an 'or where member of' filter to the current query.
+ *
+ * @param string $dn
+ *
+ * @return Builder
+ */
+ public function orWhereMemberOf($dn)
+ {
+ return $this->orWhereEquals($this->schema->memberOfRecursive(), $dn);
+ }
+
+ /**
+ * Adds a filter onto the current query.
+ *
+ * @param string $type The type of filter to add.
+ * @param array $bindings The bindings of the filter.
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function addFilter($type, array $bindings)
+ {
+ // Here we will ensure we have been given a proper filter type.
+ if (!array_key_exists($type, $this->filters)) {
+ throw new InvalidArgumentException("Invalid filter type: {$type}.");
+ }
+
+ // The required filter key bindings.
+ $required = ['field', 'operator', 'value'];
+
+ // Here we will ensure the proper key bindings are given.
+ if (count(array_intersect_key(array_flip($required), $bindings)) !== count($required)) {
+ // Retrieve the keys that are missing in the bindings array.
+ $missing = implode(', ', array_diff($required, array_flip($bindings)));
+
+ throw new InvalidArgumentException("Invalid filter bindings. Missing: {$missing} keys.");
+ }
+
+ $this->filters[$type][] = $bindings;
+
+ return $this;
+ }
+
+ /**
+ * Clear the query builders filters.
+ *
+ * @return $this
+ */
+ public function clearFilters()
+ {
+ foreach ($this->filters as $type => $filters) {
+ $this->filters[$type] = [];
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns true / false depending if the current object
+ * contains selects.
+ *
+ * @return bool
+ */
+ public function hasSelects()
+ {
+ return count($this->getSelects()) > 0;
+ }
+
+ /**
+ * Returns the current selected fields to retrieve.
+ *
+ * @return array
+ */
+ public function getSelects()
+ {
+ $selects = $this->columns;
+
+ // If the asterisk is not provided in the selected columns, we need to
+ // ensure we always select the object class and category, as these
+ // are used for constructing models. The asterisk indicates that
+ // we want all attributes returned for LDAP records.
+ if (!in_array('*', $selects)) {
+ $selects[] = $this->schema->objectCategory();
+ $selects[] = $this->schema->objectClass();
+ }
+
+ return $selects;
+ }
+
+ /**
+ * Sorts the LDAP search results by the specified field and direction.
+ *
+ * @param string $field
+ * @param string $direction
+ * @param int|null $flags
+ *
+ * @return Builder
+ */
+ public function sortBy($field, $direction = 'asc', $flags = null)
+ {
+ $this->sortByField = $field;
+
+ // Normalize direction.
+ $direction = strtolower($direction);
+
+ if ($direction === 'asc' || $direction === 'desc') {
+ $this->sortByDirection = $direction;
+ }
+
+ if (is_null($flags)) {
+ $this->sortByFlags = SORT_NATURAL + SORT_FLAG_CASE;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the query to search on the base distinguished name.
+ *
+ * This will result in one record being returned.
+ *
+ * @return Builder
+ */
+ public function read()
+ {
+ $this->type = 'read';
+
+ return $this;
+ }
+
+ /**
+ * Set the query to search one level on the base distinguished name.
+ *
+ * @return Builder
+ */
+ public function listing()
+ {
+ $this->type = 'listing';
+
+ return $this;
+ }
+
+ /**
+ * Sets the query to search the entire directory on the base distinguished name.
+ *
+ * @return Builder
+ */
+ public function recursive()
+ {
+ $this->type = 'search';
+
+ return $this;
+ }
+
+ /**
+ * Whether to return the LDAP results in their raw format.
+ *
+ * @param bool $raw
+ *
+ * @return Builder
+ */
+ public function raw($raw = true)
+ {
+ $this->raw = (bool) $raw;
+
+ return $this;
+ }
+
+ /**
+ * Whether the current query is nested.
+ *
+ * @param bool $nested
+ *
+ * @return Builder
+ */
+ public function nested($nested = true)
+ {
+ $this->nested = (bool) $nested;
+
+ return $this;
+ }
+
+ /**
+ * Enables caching on the current query until the given date.
+ *
+ * If flushing is enabled, the query cache will be flushed and then re-cached.
+ *
+ * @param \DateTimeInterface $until When to expire the query cache.
+ * @param bool $flush Whether to force-flush the query cache.
+ *
+ * @return $this
+ */
+ public function cache(\DateTimeInterface $until = null, $flush = false)
+ {
+ $this->caching = true;
+ $this->cacheUntil = $until;
+ $this->flushCache = $flush;
+
+ return $this;
+ }
+
+ /**
+ * Returns an escaped string for use in an LDAP filter.
+ *
+ * @param string $value
+ * @param string $ignore
+ * @param int $flags
+ *
+ * @return string
+ */
+ public function escape($value, $ignore = '', $flags = 0)
+ {
+ return ldap_escape($value, $ignore, $flags);
+ }
+
+ /**
+ * Returns the query builders sort by field.
+ *
+ * @return string
+ */
+ public function getSortByField()
+ {
+ return $this->sortByField;
+ }
+
+ /**
+ * Returns the query builders sort by direction.
+ *
+ * @return string
+ */
+ public function getSortByDirection()
+ {
+ return $this->sortByDirection;
+ }
+
+ /**
+ * Returns the query builders sort by flags.
+ *
+ * @return int
+ */
+ public function getSortByFlags()
+ {
+ return $this->sortByFlags;
+ }
+
+ /**
+ * Returns true / false if the current query is nested.
+ *
+ * @return bool
+ */
+ public function isNested()
+ {
+ return $this->nested === true;
+ }
+
+ /**
+ * Returns bool that determines whether the current
+ * query builder will return raw results.
+ *
+ * @return bool
+ */
+ public function isRaw()
+ {
+ return $this->raw;
+ }
+
+ /**
+ * Returns bool that determines whether the current
+ * query builder will return paginated results.
+ *
+ * @return bool
+ */
+ public function isPaginated()
+ {
+ return $this->paginated;
+ }
+
+ /**
+ * Returns bool that determines whether the current
+ * query builder will return sorted results.
+ *
+ * @return bool
+ */
+ public function isSorted()
+ {
+ return $this->sortByField ? true : false;
+ }
+
+ /**
+ * Handle dynamic method calls on the query builder object to be directed to the query processor.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ // We'll check if the beginning of the method being called contains
+ // 'where'. If so, we'll assume it's a dynamic 'where' clause.
+ if (substr($method, 0, 5) === 'where') {
+ return $this->dynamicWhere($method, $parameters);
+ }
+
+ return call_user_func_array([$this->newProcessor(), $method], $parameters);
+ }
+
+ /**
+ * Handles dynamic "where" clauses to the query.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return Builder
+ */
+ public function dynamicWhere($method, $parameters)
+ {
+ $finder = substr($method, 5);
+
+ $segments = preg_split('/(And|Or)(?=[A-Z])/', $finder, -1, PREG_SPLIT_DELIM_CAPTURE);
+
+ // The connector variable will determine which connector will be used for the
+ // query condition. We will change it as we come across new boolean values
+ // in the dynamic method strings, which could contain a number of these.
+ $connector = 'and';
+
+ $index = 0;
+
+ foreach ($segments as $segment) {
+ // If the segment is not a boolean connector, we can assume it is a column's name
+ // and we will add it to the query as a new constraint as a where clause, then
+ // we can keep iterating through the dynamic method string's segments again.
+ if ($segment != 'And' && $segment != 'Or') {
+ $this->addDynamic($segment, $connector, $parameters, $index);
+
+ $index++;
+ }
+
+ // Otherwise, we will store the connector so we know how the next where clause we
+ // find in the query should be connected to the previous ones, meaning we will
+ // have the proper boolean connector to connect the next where clause found.
+ else {
+ $connector = $segment;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds an array of wheres to the current query.
+ *
+ * @param array $wheres
+ * @param string $boolean
+ * @param bool $raw
+ *
+ * @return Builder
+ */
+ protected function addArrayOfWheres($wheres, $boolean, $raw)
+ {
+ foreach ($wheres as $key => $value) {
+ if (is_numeric($key) && is_array($value)) {
+ // If the key is numeric and the value is an array, we'll
+ // assume we've been given an array with conditionals.
+ list($field, $condition) = $value;
+
+ // Since a value is optional for some conditionals, we will
+ // try and retrieve the third parameter from the array,
+ // but is entirely optional.
+ $value = Arr::get($value, 2);
+
+ $this->where($field, $condition, $value, $boolean);
+ } else {
+ // If the value is not an array, we will assume an equals clause.
+ $this->where($key, Operator::$equals, $value, $boolean, $raw);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a single dynamic where clause statement to the query.
+ *
+ * @param string $segment
+ * @param string $connector
+ * @param array $parameters
+ * @param int $index
+ *
+ * @return void
+ */
+ protected function addDynamic($segment, $connector, $parameters, $index)
+ {
+ // We'll format the 'where' boolean and field here to avoid casing issues.
+ $bool = strtolower($connector);
+ $field = strtolower($segment);
+
+ $this->where($field, '=', $parameters[$index], $bool);
+ }
+
+ /**
+ * Logs the given executed query information by firing its query event.
+ *
+ * @param Builder $query
+ * @param string $type
+ * @param null|float $time
+ */
+ protected function logQuery($query, $type, $time = null)
+ {
+ $args = [$query, $time];
+
+ switch ($type) {
+ case 'listing':
+ $event = new Events\Listing(...$args);
+ break;
+ case 'read':
+ $event = new Events\Read(...$args);
+ break;
+ case 'paginate':
+ $event = new Events\Paginate(...$args);
+ break;
+ default:
+ $event = new Events\Search(...$args);
+ break;
+ }
+
+ $this->fireQueryEvent($event);
+ }
+
+ /**
+ * Fires the given query event.
+ *
+ * @param QueryExecuted $event
+ */
+ protected function fireQueryEvent(QueryExecuted $event)
+ {
+ Adldap::getEventDispatcher()->fire($event);
+ }
+
+ /**
+ * Get the elapsed time since a given starting point.
+ *
+ * @param int $start
+ *
+ * @return float
+ */
+ protected function getElapsedTime($start)
+ {
+ return round((microtime(true) - $start) * 1000, 2);
+ }
+
+ /**
+ * Returns a new query Processor instance.
+ *
+ * @return Processor
+ */
+ protected function newProcessor()
+ {
+ return new Processor($this);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Cache.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Cache.php
new file mode 100644
index 0000000..9b0206a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Cache.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace Adldap\Query;
+
+use Closure;
+use Psr\SimpleCache\CacheInterface;
+
+class Cache
+{
+ /**
+ * The cache driver.
+ *
+ * @var CacheInterface
+ */
+ protected $store;
+
+ /**
+ * Constructor.
+ *
+ * @param CacheInterface $store
+ */
+ public function __construct(CacheInterface $store)
+ {
+ $this->store = $store;
+ }
+
+ /**
+ * Get an item from the cache.
+ *
+ * @param string $key
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ *
+ * @return mixed
+ */
+ public function get($key)
+ {
+ return $this->store->get($key);
+ }
+
+ /**
+ * Store an item in the cache.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param \DateTimeInterface|\DateInterval|int|null $ttl
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ *
+ * @return bool
+ */
+ public function put($key, $value, $ttl = null)
+ {
+ return $this->store->set($key, $value, $ttl);
+ }
+
+ /**
+ * Get an item from the cache, or execute the given Closure and store the result.
+ *
+ * @param string $key
+ * @param \DateTimeInterface|\DateInterval|int|null $ttl
+ * @param Closure $callback
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ *
+ * @return mixed
+ */
+ public function remember($key, $ttl, Closure $callback)
+ {
+ $value = $this->get($key);
+
+ if (!is_null($value)) {
+ return $value;
+ }
+
+ $this->put($key, $value = $callback(), $ttl);
+
+ return $value;
+ }
+
+ /**
+ * Delete an item from the cache.
+ *
+ * @param string $key
+ *
+ * @throws \Psr\Cache\InvalidArgumentException
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ *
+ * @return bool
+ */
+ public function delete($key)
+ {
+ return $this->store->delete($key);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Collection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Collection.php
new file mode 100644
index 0000000..b9b6616
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Collection.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Adldap\Query;
+
+use Adldap\Models\Model;
+use Illuminate\Support\Collection as BaseCollection;
+
+class Collection extends BaseCollection
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function valueRetriever($value)
+ {
+ if ($this->useAsCallable($value)) {
+ return $value;
+ }
+
+ return function ($item) use ($value) {
+ if ($item instanceof Model) {
+ return $item->getFirstAttribute($value);
+ }
+
+ return data_get($item, $value);
+ };
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Listing.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Listing.php
new file mode 100644
index 0000000..0ca05b7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Listing.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Query\Events;
+
+class Listing extends QueryExecuted
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Paginate.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Paginate.php
new file mode 100644
index 0000000..2a7666d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Paginate.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Query\Events;
+
+class Paginate extends QueryExecuted
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/QueryExecuted.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/QueryExecuted.php
new file mode 100644
index 0000000..3779276
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/QueryExecuted.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Adldap\Query\Events;
+
+use Adldap\Query\Builder;
+
+class QueryExecuted
+{
+ /**
+ * The LDAP filter that was used for the query.
+ *
+ * @var string
+ */
+ protected $query;
+
+ /**
+ * The number of milliseconds it took to execute the query.
+ *
+ * @var float
+ */
+ protected $time;
+
+ /**
+ * Constructor.
+ *
+ * @param Builder $query
+ * @param null|float $time
+ */
+ public function __construct(Builder $query, $time = null)
+ {
+ $this->query = $query;
+ $this->time = $time;
+ }
+
+ /**
+ * Returns the LDAP filter that was used for the query.
+ *
+ * @return Builder
+ */
+ public function getQuery()
+ {
+ return $this->query;
+ }
+
+ /**
+ * Returns the number of milliseconds it took to execute the query.
+ *
+ * @return float|null
+ */
+ public function getTime()
+ {
+ return $this->time;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Read.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Read.php
new file mode 100644
index 0000000..4e0e65d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Read.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Query\Events;
+
+class Read extends QueryExecuted
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Search.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Search.php
new file mode 100644
index 0000000..35fe913
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Events/Search.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Query\Events;
+
+class Search extends QueryExecuted
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Factory.php
new file mode 100644
index 0000000..199107e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Factory.php
@@ -0,0 +1,297 @@
+<?php
+
+namespace Adldap\Query;
+
+use Adldap\Models\RootDse;
+use Adldap\Schemas\ActiveDirectory;
+use Adldap\Schemas\SchemaInterface;
+use Adldap\Connections\ConnectionInterface;
+
+/**
+ * Adldap2 Search Factory.
+ *
+ * Constructs new LDAP queries.
+ *
+ *
+ * @mixin Builder
+ */
+class Factory
+{
+ /**
+ * @var ConnectionInterface
+ */
+ protected $connection;
+
+ /**
+ * Stores the current schema instance.
+ *
+ * @var SchemaInterface
+ */
+ protected $schema;
+
+ /**
+ * The base DN to use for the search.
+ *
+ * @var string|null
+ */
+ protected $base;
+
+ /**
+ * The query cache.
+ *
+ * @var Cache
+ */
+ protected $cache;
+
+ /**
+ * Constructor.
+ *
+ * @param ConnectionInterface $connection The connection to use when constructing a new query.
+ * @param SchemaInterface|null $schema The schema to use for the query and models located.
+ * @param string $baseDn The base DN to use for all searches.
+ */
+ public function __construct(ConnectionInterface $connection, SchemaInterface $schema = null, $baseDn = '')
+ {
+ $this->setConnection($connection)
+ ->setSchema($schema)
+ ->setBaseDn($baseDn);
+ }
+
+ /**
+ * Sets the connection property.
+ *
+ * @param ConnectionInterface $connection
+ *
+ * @return $this
+ */
+ public function setConnection(ConnectionInterface $connection)
+ {
+ $this->connection = $connection;
+
+ return $this;
+ }
+
+ /**
+ * Sets the schema property.
+ *
+ * @param SchemaInterface|null $schema
+ *
+ * @return $this
+ */
+ public function setSchema(SchemaInterface $schema = null)
+ {
+ $this->schema = $schema ?: new ActiveDirectory();
+
+ return $this;
+ }
+
+ /**
+ * Sets the base distinguished name to perform searches upon.
+ *
+ * @param string $base
+ *
+ * @return $this
+ */
+ public function setBaseDn($base = '')
+ {
+ $this->base = $base;
+
+ return $this;
+ }
+
+ /**
+ * Sets the cache for storing query results.
+ *
+ * @param Cache $cache
+ *
+ * @return $this
+ */
+ public function setCache(Cache $cache)
+ {
+ $this->cache = $cache;
+
+ return $this;
+ }
+
+ /**
+ * Returns a new query builder instance.
+ *
+ * @return Builder
+ */
+ public function newQuery()
+ {
+ return $this->newBuilder()->in($this->base);
+ }
+
+ /**
+ * Performs a global 'all' search query on the current
+ * connection by performing a search for all entries
+ * that contain a common name attribute.
+ *
+ * @return \Adldap\Query\Collection|array
+ */
+ public function get()
+ {
+ return $this->newQuery()->whereHas($this->schema->commonName())->get();
+ }
+
+ /**
+ * Returns a query builder scoped to users.
+ *
+ * @return Builder
+ */
+ public function users()
+ {
+ $wheres = [
+ [$this->schema->objectClass(), Operator::$equals, $this->schema->objectClassUser()],
+ [$this->schema->objectCategory(), Operator::$equals, $this->schema->objectCategoryPerson()],
+ ];
+
+ // OpenLDAP doesn't like specifying the omission of user objectclasses
+ // equal to `contact`. We'll make sure we're working with
+ // ActiveDirectory before adding this filter.
+ if (is_a($this->schema, ActiveDirectory::class)) {
+ $wheres[] = [$this->schema->objectClass(), Operator::$doesNotEqual, $this->schema->objectClassContact()];
+ }
+
+ return $this->where($wheres);
+ }
+
+ /**
+ * Returns a query builder scoped to printers.
+ *
+ * @return Builder
+ */
+ public function printers()
+ {
+ return $this->where([
+ $this->schema->objectClass() => $this->schema->objectClassPrinter(),
+ ]);
+ }
+
+ /**
+ * Returns a query builder scoped to organizational units.
+ *
+ * @return Builder
+ */
+ public function ous()
+ {
+ return $this->where([
+ $this->schema->objectClass() => $this->schema->objectClassOu(),
+ ]);
+ }
+
+ /**
+ * Returns a query builder scoped to organizations.
+ *
+ * @return Builder
+ */
+ public function organizations()
+ {
+ return $this->where([
+ $this->schema->objectClass() => $this->schema->objectClassOrganization(),
+ ]);
+ }
+
+ /**
+ * Returns a query builder scoped to groups.
+ *
+ * @return Builder
+ */
+ public function groups()
+ {
+ return $this->where([
+ $this->schema->objectClass() => $this->schema->objectClassGroup(),
+ ]);
+ }
+
+ /**
+ * Returns a query builder scoped to containers.
+ *
+ * @return Builder
+ */
+ public function containers()
+ {
+ return $this->where([
+ $this->schema->objectClass() => $this->schema->objectClassContainer(),
+ ]);
+ }
+
+ /**
+ * Returns a query builder scoped to contacts.
+ *
+ * @return Builder
+ */
+ public function contacts()
+ {
+ return $this->where([
+ $this->schema->objectClass() => $this->schema->objectClassContact(),
+ ]);
+ }
+
+ /**
+ * Returns a query builder scoped to computers.
+ *
+ * @return Builder
+ */
+ public function computers()
+ {
+ return $this->where([
+ $this->schema->objectClass() => $this->schema->objectClassComputer(),
+ ]);
+ }
+
+ /**
+ * Returns the root DSE record.
+ *
+ * @return RootDse|null
+ */
+ public function getRootDse()
+ {
+ $query = $this->newQuery();
+
+ $root = $query->in('')->read()->whereHas($this->schema->objectClass())->first();
+
+ if ($root) {
+ return (new RootDse([], $query))
+ ->setRawAttributes($root->getAttributes());
+ }
+ }
+
+ /**
+ * Handle dynamic method calls on the query builder object.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ return call_user_func_array([$this->newQuery(), $method], $parameters);
+ }
+
+ /**
+ * Returns a new query grammar instance.
+ *
+ * @return Grammar
+ */
+ protected function newGrammar()
+ {
+ return new Grammar();
+ }
+
+ /**
+ * Returns a new query builder instance.
+ *
+ * @return Builder
+ */
+ protected function newBuilder()
+ {
+ $builder = new Builder($this->connection, $this->newGrammar(), $this->schema);
+
+ $builder->setCache($this->cache);
+
+ return $builder;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Grammar.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Grammar.php
new file mode 100644
index 0000000..dcda3d7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Grammar.php
@@ -0,0 +1,390 @@
+<?php
+
+namespace Adldap\Query;
+
+class Grammar
+{
+ /**
+ * Wraps a query string in brackets.
+ *
+ * Produces: (query)
+ *
+ * @param string $query
+ * @param string $prefix
+ * @param string $suffix
+ *
+ * @return string
+ */
+ public function wrap($query, $prefix = '(', $suffix = ')')
+ {
+ return $prefix.$query.$suffix;
+ }
+
+ /**
+ * Compiles the Builder instance into an LDAP query string.
+ *
+ * @param Builder $builder
+ *
+ * @return string
+ */
+ public function compile(Builder $builder)
+ {
+ $ands = $builder->filters['and'];
+ $ors = $builder->filters['or'];
+ $raws = $builder->filters['raw'];
+
+ $query = $this->concatenate($raws);
+
+ $query = $this->compileWheres($ands, $query);
+
+ $query = $this->compileOrWheres($ors, $query);
+
+ // We need to check if the query is already nested, otherwise
+ // we'll nest it here and return the result.
+ if (!$builder->isNested()) {
+ $total = count($ands) + count($raws);
+
+ // Make sure we wrap the query in an 'and' if using
+ // multiple filters. We also need to check if only
+ // one where is used with multiple orWheres, that
+ // we wrap it in an `and` query.
+ if ($total > 1 || (count($ands) === 1 && count($ors) > 0)) {
+ $query = $this->compileAnd($query);
+ }
+ }
+
+ return $query;
+ }
+
+ /**
+ * Concatenates filters into a single string.
+ *
+ * @param array $bindings
+ *
+ * @return string
+ */
+ public function concatenate(array $bindings = [])
+ {
+ // Filter out empty query segments.
+ $bindings = array_filter($bindings, function ($value) {
+ return (string) $value !== '';
+ });
+
+ return implode('', $bindings);
+ }
+
+ /**
+ * Returns a query string for equals.
+ *
+ * Produces: (field=value)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileEquals($field, $value)
+ {
+ return $this->wrap($field.Operator::$equals.$value);
+ }
+
+ /**
+ * Returns a query string for does not equal.
+ *
+ * Produces: (!(field=value))
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileDoesNotEqual($field, $value)
+ {
+ return $this->compileNot($this->compileEquals($field, $value));
+ }
+
+ /**
+ * Alias for does not equal operator (!=) operator.
+ *
+ * Produces: (!(field=value))
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileDoesNotEqualAlias($field, $value)
+ {
+ return $this->compileDoesNotEqual($field, $value);
+ }
+
+ /**
+ * Returns a query string for greater than or equals.
+ *
+ * Produces: (field>=value)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileGreaterThanOrEquals($field, $value)
+ {
+ return $this->wrap($field.Operator::$greaterThanOrEquals.$value);
+ }
+
+ /**
+ * Returns a query string for less than or equals.
+ *
+ * Produces: (field<=value)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileLessThanOrEquals($field, $value)
+ {
+ return $this->wrap($field.Operator::$lessThanOrEquals.$value);
+ }
+
+ /**
+ * Returns a query string for approximately equals.
+ *
+ * Produces: (field~=value)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileApproximatelyEquals($field, $value)
+ {
+ return $this->wrap($field.Operator::$approximatelyEquals.$value);
+ }
+
+ /**
+ * Returns a query string for starts with.
+ *
+ * Produces: (field=value*)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileStartsWith($field, $value)
+ {
+ return $this->wrap($field.Operator::$equals.$value.Operator::$has);
+ }
+
+ /**
+ * Returns a query string for does not start with.
+ *
+ * Produces: (!(field=*value))
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileNotStartsWith($field, $value)
+ {
+ return $this->compileNot($this->compileStartsWith($field, $value));
+ }
+
+ /**
+ * Returns a query string for ends with.
+ *
+ * Produces: (field=*value)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileEndsWith($field, $value)
+ {
+ return $this->wrap($field.Operator::$equals.Operator::$has.$value);
+ }
+
+ /**
+ * Returns a query string for does not end with.
+ *
+ * Produces: (!(field=value*))
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileNotEndsWith($field, $value)
+ {
+ return $this->compileNot($this->compileEndsWith($field, $value));
+ }
+
+ /**
+ * Returns a query string for contains.
+ *
+ * Produces: (field=*value*)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileContains($field, $value)
+ {
+ return $this->wrap($field.Operator::$equals.Operator::$has.$value.Operator::$has);
+ }
+
+ /**
+ * Returns a query string for does not contain.
+ *
+ * Produces: (!(field=*value*))
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileNotContains($field, $value)
+ {
+ return $this->compileNot($this->compileContains($field, $value));
+ }
+
+ /**
+ * Returns a query string for a where has.
+ *
+ * Produces: (field=*)
+ *
+ * @param string $field
+ *
+ * @return string
+ */
+ public function compileHas($field)
+ {
+ return $this->wrap($field.Operator::$equals.Operator::$has);
+ }
+
+ /**
+ * Returns a query string for a where does not have.
+ *
+ * Produces: (!(field=*))
+ *
+ * @param string $field
+ *
+ * @return string
+ */
+ public function compileNotHas($field)
+ {
+ return $this->compileNot($this->compileHas($field));
+ }
+
+ /**
+ * Wraps the inserted query inside an AND operator.
+ *
+ * Produces: (&query)
+ *
+ * @param string $query
+ *
+ * @return string
+ */
+ public function compileAnd($query)
+ {
+ return $query ? $this->wrap($query, '(&') : '';
+ }
+
+ /**
+ * Wraps the inserted query inside an OR operator.
+ *
+ * Produces: (|query)
+ *
+ * @param string $query
+ *
+ * @return string
+ */
+ public function compileOr($query)
+ {
+ return $query ? $this->wrap($query, '(|') : '';
+ }
+
+ /**
+ * Wraps the inserted query inside an NOT operator.
+ *
+ * @param string $query
+ *
+ * @return string
+ */
+ public function compileNot($query)
+ {
+ return $query ? $this->wrap($query, '(!') : '';
+ }
+
+ /**
+ * Assembles all where clauses in the current wheres property.
+ *
+ * @param array $wheres
+ * @param string $query
+ *
+ * @return string
+ */
+ protected function compileWheres(array $wheres = [], $query = '')
+ {
+ foreach ($wheres as $where) {
+ $query .= $this->compileWhere($where);
+ }
+
+ return $query;
+ }
+
+ /**
+ * Assembles all or where clauses in the current orWheres property.
+ *
+ * @param array $orWheres
+ * @param string $query
+ *
+ * @return string
+ */
+ protected function compileOrWheres(array $orWheres = [], $query = '')
+ {
+ $or = '';
+
+ foreach ($orWheres as $where) {
+ $or .= $this->compileWhere($where);
+ }
+
+ // Make sure we wrap the query in an 'or' if using multiple
+ // orWheres. For example (|(QUERY)(ORWHEREQUERY)).
+ if (($query && count($orWheres) > 0) || count($orWheres) > 1) {
+ $query .= $this->compileOr($or);
+ } else {
+ $query .= $or;
+ }
+
+ return $query;
+ }
+
+ /**
+ * Assembles a single where query based
+ * on its operator and returns it.
+ *
+ * @param array $where
+ *
+ * @return string|null
+ */
+ protected function compileWhere(array $where)
+ {
+ // Get the name of the operator.
+ if ($name = array_search($where['operator'], Operator::all())) {
+ // If the name was found we'll camel case it
+ // to run it through the compile method.
+ $method = 'compile'.ucfirst($name);
+
+ // Make sure the compile method exists for the operator.
+ if (method_exists($this, $method)) {
+ return $this->{$method}($where['field'], $where['value']);
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Operator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Operator.php
new file mode 100644
index 0000000..75b3289
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Operator.php
@@ -0,0 +1,116 @@
+<?php
+
+namespace Adldap\Query;
+
+use ReflectionClass;
+
+class Operator
+{
+ /**
+ * The 'has' wildcard operator.
+ *
+ * @var string
+ */
+ public static $has = '*';
+
+ /**
+ * The custom `notHas` operator.
+ *
+ * @var string
+ */
+ public static $notHas = '!*';
+
+ /**
+ * The equals operator.
+ *
+ * @var string
+ */
+ public static $equals = '=';
+
+ /**
+ * The does not equal operator.
+ *
+ * @var string
+ */
+ public static $doesNotEqual = '!';
+
+ /**
+ * The does not equal operator (alias).
+ *
+ * @var string
+ */
+ public static $doesNotEqualAlias = '!=';
+
+ /**
+ * The greater than or equal to operator.
+ *
+ * @var string
+ */
+ public static $greaterThanOrEquals = '>=';
+
+ /**
+ * The less than or equal to operator.
+ *
+ * @var string
+ */
+ public static $lessThanOrEquals = '<=';
+
+ /**
+ * The approximately equal to operator.
+ *
+ * @var string
+ */
+ public static $approximatelyEquals = '~=';
+
+ /**
+ * The custom starts with operator.
+ *
+ * @var string
+ */
+ public static $startsWith = 'starts_with';
+
+ /**
+ * The custom not starts with operator.
+ *
+ * @var string
+ */
+ public static $notStartsWith = 'not_starts_with';
+
+ /**
+ * The custom ends with operator.
+ *
+ * @var string
+ */
+ public static $endsWith = 'ends_with';
+
+ /**
+ * The custom not ends with operator.
+ *
+ * @var string
+ */
+ public static $notEndsWith = 'not_ends_with';
+
+ /**
+ * The custom contains operator.
+ *
+ * @var string
+ */
+ public static $contains = 'contains';
+
+ /**
+ * The custom not contains operator.
+ *
+ * @var string
+ */
+ public static $notContains = 'not_contains';
+
+ /**
+ * Returns all available operators.
+ *
+ * @return array
+ */
+ public static function all()
+ {
+ return (new ReflectionClass(new static()))->getStaticProperties();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Paginator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Paginator.php
new file mode 100644
index 0000000..0f61fe2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Paginator.php
@@ -0,0 +1,206 @@
+<?php
+
+namespace Adldap\Query;
+
+use Countable;
+use ArrayIterator;
+use IteratorAggregate;
+
+class Paginator implements Countable, IteratorAggregate
+{
+ /**
+ * The complete results array.
+ *
+ * @var array
+ */
+ protected $results = [];
+
+ /**
+ * The total amount of pages.
+ *
+ * @var int
+ */
+ protected $pages;
+
+ /**
+ * The amount of entries per page.
+ *
+ * @var int
+ */
+ protected $perPage;
+
+ /**
+ * The current page number.
+ *
+ * @var int
+ */
+ protected $currentPage;
+
+ /**
+ * The current entry offset number.
+ *
+ * @var int
+ */
+ protected $currentOffset;
+
+ /**
+ * Constructor.
+ *
+ * @param array $results
+ * @param int $perPage
+ * @param int $currentPage
+ * @param int $pages
+ */
+ public function __construct(array $results = [], $perPage = 50, $currentPage = 0, $pages = 0)
+ {
+ $this->setResults($results)
+ ->setPerPage($perPage)
+ ->setCurrentPage($currentPage)
+ ->setPages($pages)
+ ->setCurrentOffset(($this->getCurrentPage() * $this->getPerPage()));
+ }
+
+ /**
+ * Get an iterator for the entries.
+ *
+ * @return ArrayIterator
+ */
+ public function getIterator()
+ {
+ $entries = array_slice($this->getResults(), $this->getCurrentOffset(), $this->getPerPage(), true);
+
+ return new ArrayIterator($entries);
+ }
+
+ /**
+ * Returns the complete results array.
+ *
+ * @return array
+ */
+ public function getResults()
+ {
+ return $this->results;
+ }
+
+ /**
+ * Returns the total amount of pages
+ * in a paginated result.
+ *
+ * @return int
+ */
+ public function getPages()
+ {
+ return $this->pages;
+ }
+
+ /**
+ * Returns the total amount of entries
+ * allowed per page.
+ *
+ * @return int
+ */
+ public function getPerPage()
+ {
+ return $this->perPage;
+ }
+
+ /**
+ * Returns the current page number.
+ *
+ * @return int
+ */
+ public function getCurrentPage()
+ {
+ return $this->currentPage;
+ }
+
+ /**
+ * Returns the current offset number.
+ *
+ * @return int
+ */
+ public function getCurrentOffset()
+ {
+ return $this->currentOffset;
+ }
+
+ /**
+ * Returns the total amount of results.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->results);
+ }
+
+ /**
+ * Sets the results array property.
+ *
+ * @param array $results
+ *
+ * @return Paginator
+ */
+ protected function setResults(array $results)
+ {
+ $this->results = $results;
+
+ return $this;
+ }
+
+ /**
+ * Sets the total number of pages.
+ *
+ * @param int $pages
+ *
+ * @return Paginator
+ */
+ protected function setPages($pages = 0)
+ {
+ $this->pages = (int) $pages;
+
+ return $this;
+ }
+
+ /**
+ * Sets the number of entries per page.
+ *
+ * @param int $perPage
+ *
+ * @return Paginator
+ */
+ protected function setPerPage($perPage = 50)
+ {
+ $this->perPage = (int) $perPage;
+
+ return $this;
+ }
+
+ /**
+ * Sets the current page number.
+ *
+ * @param int $currentPage
+ *
+ * @return Paginator
+ */
+ protected function setCurrentPage($currentPage = 0)
+ {
+ $this->currentPage = (int) $currentPage;
+
+ return $this;
+ }
+
+ /**
+ * Sets the current offset number.
+ *
+ * @param int $offset
+ *
+ * @return Paginator
+ */
+ protected function setCurrentOffset($offset = 0)
+ {
+ $this->currentOffset = (int) $offset;
+
+ return $this;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Processor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Processor.php
new file mode 100644
index 0000000..e4e5329
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Query/Processor.php
@@ -0,0 +1,211 @@
+<?php
+
+namespace Adldap\Query;
+
+use Adldap\Models\Entry;
+use Adldap\Models\Model;
+use InvalidArgumentException;
+use Adldap\Schemas\SchemaInterface;
+use Adldap\Connections\ConnectionInterface;
+
+class Processor
+{
+ /**
+ * @var Builder
+ */
+ protected $builder;
+
+ /**
+ * @var ConnectionInterface
+ */
+ protected $connection;
+
+ /**
+ * @var SchemaInterface
+ */
+ protected $schema;
+
+ /**
+ * Constructor.
+ *
+ * @param Builder $builder
+ */
+ public function __construct(Builder $builder)
+ {
+ $this->builder = $builder;
+ $this->schema = $builder->getSchema();
+ $this->connection = $builder->getConnection();
+ }
+
+ /**
+ * Processes LDAP search results and constructs their model instances.
+ *
+ * @param array $entries The LDAP entries to process.
+ *
+ * @return Collection|array
+ */
+ public function process($entries)
+ {
+ if ($this->builder->isRaw()) {
+ // If the builder is asking for a raw
+ // LDAP result, we can return here.
+ return $entries;
+ }
+
+ $models = [];
+
+ if (array_key_exists('count', $entries)) {
+ for ($i = 0; $i < $entries['count']; $i++) {
+ // We'll go through each entry and construct a new
+ // model instance with the raw LDAP attributes.
+ $models[] = $this->newLdapEntry($entries[$i]);
+ }
+ }
+
+ // If the query contains paginated results, we'll return them here.
+ if ($this->builder->isPaginated()) {
+ return $models;
+ }
+
+ // If the query is requested to be sorted, we'll perform
+ // that here and return the resulting collection.
+ if ($this->builder->isSorted()) {
+ return $this->processSort($models);
+ }
+
+ // Otherwise, we'll return a regular unsorted collection.
+ return $this->newCollection($models);
+ }
+
+ /**
+ * Processes paginated LDAP results.
+ *
+ * @param array $pages
+ * @param int $perPage
+ * @param int $currentPage
+ *
+ * @return Paginator
+ */
+ public function processPaginated(array $pages = [], $perPage = 50, $currentPage = 0)
+ {
+ $models = [];
+
+ foreach ($pages as $entries) {
+ // Go through each page and process the results into an objects array.
+ $models = array_merge($models, $this->process($entries));
+ }
+
+ $models = $this->processSort($models)->toArray();
+
+ return $this->newPaginator($models, $perPage, $currentPage, count($pages));
+ }
+
+ /**
+ * Returns a new LDAP Entry instance.
+ *
+ * @param array $attributes
+ *
+ * @return Entry
+ */
+ public function newLdapEntry(array $attributes = [])
+ {
+ $objectClass = $this->schema->objectClass();
+
+ // We need to ensure the record contains an object class to be able to
+ // determine its type. Otherwise, we create a default Entry model.
+ if (array_key_exists($objectClass, $attributes) && array_key_exists(0, $attributes[$objectClass])) {
+ // Retrieve all of the object classes from the LDAP
+ // entry and lowercase them for comparisons.
+ $classes = array_map('strtolower', $attributes[$objectClass]);
+
+ // Retrieve the model mapping.
+ $models = $this->schema->objectClassModelMap();
+
+ // Retrieve the object class mappings (with strtolower keys).
+ $mappings = array_map('strtolower', array_keys($models));
+
+ // Retrieve the model from the map using the entry's object class.
+ $map = array_intersect($mappings, $classes);
+
+ if (count($map) > 0) {
+ // Retrieve the model using the object class.
+ $model = $models[current($map)];
+
+ // Construct and return a new model.
+ return $this->newModel([], $model)
+ ->setRawAttributes($attributes);
+ }
+ }
+
+ // A default entry model if the object class isn't found.
+ return $this->newModel()->setRawAttributes($attributes);
+ }
+
+ /**
+ * Creates a new model instance.
+ *
+ * @param array $attributes
+ * @param string|null $model
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return mixed|Entry
+ */
+ public function newModel($attributes = [], $model = null)
+ {
+ $model = (class_exists($model) ? $model : $this->schema->entryModel());
+
+ if (!is_subclass_of($model, $base = Model::class)) {
+ throw new InvalidArgumentException("The given model class '{$model}' must extend the base model class '{$base}'");
+ }
+
+ return new $model($attributes, $this->builder->newInstance());
+ }
+
+ /**
+ * Returns a new Paginator object instance.
+ *
+ * @param array $models
+ * @param int $perPage
+ * @param int $currentPage
+ * @param int $pages
+ *
+ * @return Paginator
+ */
+ public function newPaginator(array $models = [], $perPage = 25, $currentPage = 0, $pages = 1)
+ {
+ return new Paginator($models, $perPage, $currentPage, $pages);
+ }
+
+ /**
+ * Returns a new collection instance.
+ *
+ * @param array $items
+ *
+ * @return Collection
+ */
+ public function newCollection(array $items = [])
+ {
+ return new Collection($items);
+ }
+
+ /**
+ * Sorts LDAP search results.
+ *
+ * @param array $models
+ *
+ * @return Collection
+ */
+ protected function processSort(array $models = [])
+ {
+ $field = $this->builder->getSortByField();
+
+ $flags = $this->builder->getSortByFlags();
+
+ $direction = $this->builder->getSortByDirection();
+
+ $desc = ($direction === 'desc' ? true : false);
+
+ return $this->newCollection($models)->sortBy($field, $flags, $desc);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/ActiveDirectory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/ActiveDirectory.php
new file mode 100644
index 0000000..09f0314
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/ActiveDirectory.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace Adldap\Schemas;
+
+class ActiveDirectory extends Schema
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function distinguishedName()
+ {
+ return 'distinguishedname';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function distinguishedNameSubKey()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterEnabled()
+ {
+ return '(!(UserAccountControl:1.2.840.113556.1.4.803:=2))';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterDisabled()
+ {
+ return '(UserAccountControl:1.2.840.113556.1.4.803:=2)';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lockoutTime()
+ {
+ return 'lockouttime';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassGroup()
+ {
+ return 'group';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassOu()
+ {
+ return 'organizationalunit';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassPerson()
+ {
+ return 'person';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectGuid()
+ {
+ return 'objectguid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectGuidRequiresConversion()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategory()
+ {
+ return 'objectcategory';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/Directory389.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/Directory389.php
new file mode 100644
index 0000000..f51a8a4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/Directory389.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace Adldap\Schemas;
+
+class Directory389 extends Schema
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function accountName()
+ {
+ return 'uid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function distinguishedName()
+ {
+ return 'dn';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function distinguishedNameSubKey()
+ {
+ //
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterEnabled()
+ {
+ return sprintf('(!(%s=*))', $this->lockoutTime());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterDisabled()
+ {
+ return sprintf('(%s=*)', $this->lockoutTime());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lockoutTime()
+ {
+ return 'pwdAccountLockedTime';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategory()
+ {
+ return 'objectclass';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassGroup()
+ {
+ return 'groupofnames';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassOu()
+ {
+ return 'organizationalUnit';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassPerson()
+ {
+ return 'inetorgperson';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassUser()
+ {
+ return 'inetorgperson';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectGuid()
+ {
+ return 'nsuniqueid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectGuidRequiresConversion()
+ {
+ return false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/EDirectory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/EDirectory.php
new file mode 100644
index 0000000..db31011
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/EDirectory.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace Adldap\Schemas;
+
+class EDirectory extends Schema
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function accountName()
+ {
+ return 'uid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function distinguishedName()
+ {
+ return 'dn';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function distinguishedNameSubKey()
+ {
+ //
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterEnabled()
+ {
+ return sprintf('(!(%s=*))', $this->lockoutTime());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterDisabled()
+ {
+ return sprintf('(%s=*)', $this->lockoutTime());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lockoutTime()
+ {
+ return 'pwdAccountLockedTime';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategory()
+ {
+ return 'objectclass';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassGroup()
+ {
+ return 'groupofnames';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassOu()
+ {
+ return 'organizationalUnit';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassPerson()
+ {
+ return 'inetorgperson';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassUser()
+ {
+ return 'inetorgperson';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectGuid()
+ {
+ return 'guid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectGuidRequiresConversion()
+ {
+ return false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/FreeIPA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/FreeIPA.php
new file mode 100644
index 0000000..410f6f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/FreeIPA.php
@@ -0,0 +1,126 @@
+<?php
+
+namespace Adldap\Schemas;
+
+class FreeIPA extends Schema
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function accountName()
+ {
+ return 'uid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function distinguishedName()
+ {
+ return 'dn';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategory()
+ {
+ return 'objectclass';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassGroup()
+ {
+ return 'ipausergroup';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function userPrincipalName()
+ {
+ return 'krbCanonicalName';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function distinguishedNameSubKey()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterEnabled()
+ {
+ return '(!(UserAccountControl:1.2.840.113556.1.4.803:=2))';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterDisabled()
+ {
+ return '(UserAccountControl:1.2.840.113556.1.4.803:=2)';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lockoutTime()
+ {
+ return 'lockouttime';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function passwordLastSet()
+ {
+ return 'krbLastPwdChange';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassOu()
+ {
+ return 'organizationalunit';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassPerson()
+ {
+ return 'person';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassUser()
+ {
+ return 'organizationalPerson';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectGuid()
+ {
+ return 'ipaUniqueID';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectGuidRequiresConversion()
+ {
+ return false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/OpenLDAP.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/OpenLDAP.php
new file mode 100644
index 0000000..d598617
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/OpenLDAP.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace Adldap\Schemas;
+
+class OpenLDAP extends Schema
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function accountName()
+ {
+ return 'uid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function distinguishedName()
+ {
+ return 'dn';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function distinguishedNameSubKey()
+ {
+ //
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterEnabled()
+ {
+ return sprintf('(!(%s=*))', $this->lockoutTime());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filterDisabled()
+ {
+ return sprintf('(%s=*)', $this->lockoutTime());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lockoutTime()
+ {
+ return 'pwdAccountLockedTime';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategory()
+ {
+ return 'objectclass';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassGroup()
+ {
+ return 'groupofnames';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassOu()
+ {
+ return 'organizationalUnit';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassPerson()
+ {
+ return 'inetorgperson';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassUser()
+ {
+ return 'inetorgperson';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectGuid()
+ {
+ return 'entryuuid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectGuidRequiresConversion()
+ {
+ return false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/Schema.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/Schema.php
new file mode 100644
index 0000000..ac76452
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/Schema.php
@@ -0,0 +1,1264 @@
+<?php
+
+namespace Adldap\Schemas;
+
+use Adldap\Models\User;
+use Adldap\Models\Entry;
+use Adldap\Models\Group;
+use Adldap\Models\Contact;
+use Adldap\Models\Printer;
+use Adldap\Models\Computer;
+use Adldap\Models\Container;
+use Adldap\Models\Organization;
+use Adldap\Models\OrganizationalUnit;
+use Adldap\Models\ForeignSecurityPrincipal;
+
+abstract class Schema implements SchemaInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function accountExpires()
+ {
+ return 'accountexpires';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function accountName()
+ {
+ return 'samaccountname';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function accountType()
+ {
+ return 'samaccounttype';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function adminDisplayName()
+ {
+ return 'admindisplayname';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function anr()
+ {
+ return 'anr';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function badPasswordCount()
+ {
+ return 'badpwdcount';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function badPasswordTime()
+ {
+ return 'badpasswordtime';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function commonName()
+ {
+ return 'cn';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function company()
+ {
+ return 'company';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function computer()
+ {
+ return 'computer';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function computerModel()
+ {
+ return Computer::class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function configurationNamingContext()
+ {
+ return 'configurationnamingcontext';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function contact()
+ {
+ return 'contact';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function contactModel()
+ {
+ return Contact::class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function containerModel()
+ {
+ return Container::class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function country()
+ {
+ return 'c';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function createdAt()
+ {
+ return 'whencreated';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function currentTime()
+ {
+ return 'currenttime';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function defaultNamingContext()
+ {
+ return 'defaultnamingcontext';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function department()
+ {
+ return 'department';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function departmentNumber()
+ {
+ return 'departmentnumber';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function description()
+ {
+ return 'description';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function displayName()
+ {
+ return 'displayname';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dnsHostName()
+ {
+ return 'dnshostname';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function domainComponent()
+ {
+ return 'dc';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function driverName()
+ {
+ return 'drivername';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function driverVersion()
+ {
+ return 'driverversion';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function email()
+ {
+ return 'mail';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function emailNickname()
+ {
+ return 'mailnickname';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function employeeId()
+ {
+ return 'employeeid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function employeeNumber()
+ {
+ return 'employeenumber';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function employeeType()
+ {
+ return 'employeetype';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function entryModel()
+ {
+ return Entry::class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function false()
+ {
+ return 'FALSE';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function firstName()
+ {
+ return 'givenname';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function groupModel()
+ {
+ return Group::class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function groupType()
+ {
+ return 'grouptype';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function homeAddress()
+ {
+ return 'homepostaladdress';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function homeMdb()
+ {
+ return 'homemdb';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function homeDrive()
+ {
+ return 'homedrive';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function homeDirectory()
+ {
+ return 'homedirectory';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function homePhone()
+ {
+ return 'homephone';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function info()
+ {
+ return 'info';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function initials()
+ {
+ return 'initials';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function instanceType()
+ {
+ return 'instancetype';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function ipPhone()
+ {
+ return 'ipphone';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isCriticalSystemObject()
+ {
+ return 'iscriticalsystemobject';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function jpegPhoto()
+ {
+ return 'jpegphoto';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lastLogOff()
+ {
+ return 'lastlogoff';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lastLogOn()
+ {
+ return 'lastlogon';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lastLogOnTimestamp()
+ {
+ return 'lastlogontimestamp';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lastName()
+ {
+ return 'sn';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function legacyExchangeDn()
+ {
+ return 'legacyexchangedn';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function locale()
+ {
+ return 'l';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function location()
+ {
+ return 'location';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function manager()
+ {
+ return 'manager';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function managedBy()
+ {
+ return 'managedby';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function maxPasswordAge()
+ {
+ return 'maxpwdage';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function member()
+ {
+ return 'member';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function memberIdentifier()
+ {
+ return 'distinguishedname';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function memberOf()
+ {
+ return 'memberof';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function memberOfRecursive()
+ {
+ return 'memberof:1.2.840.113556.1.4.1941:';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function memberRange($from, $to)
+ {
+ return $this->member().";range={$from}-{$to}";
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function messageTrackingEnabled()
+ {
+ return 'messagetrackingenabled';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function msExchangeServer()
+ {
+ return 'ms-exch-exchange-server';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function name()
+ {
+ return 'name';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function neverExpiresDate()
+ {
+ return '9223372036854775807';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategoryComputer()
+ {
+ return 'computer';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategoryContainer()
+ {
+ return 'container';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategoryExchangePrivateMdb()
+ {
+ return 'msexchprivatemdb';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategoryExchangeServer()
+ {
+ return 'msExchExchangeServer';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategoryExchangeStorageGroup()
+ {
+ return 'msExchStorageGroup';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategoryGroup()
+ {
+ return 'group';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategoryOrganizationalUnit()
+ {
+ return 'organizational-unit';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategoryPerson()
+ {
+ return 'person';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectCategoryPrinter()
+ {
+ return 'print-queue';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClass()
+ {
+ return 'objectclass';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassComputer()
+ {
+ return 'computer';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassContact()
+ {
+ return 'contact';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassContainer()
+ {
+ return 'container';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassOrganization()
+ {
+ return 'organization';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassPrinter()
+ {
+ return 'printqueue';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassUser()
+ {
+ return 'user';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassForeignSecurityPrincipal()
+ {
+ return 'foreignsecurityprincipal';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectClassModelMap()
+ {
+ return [
+ $this->objectClassComputer() => $this->computerModel(),
+ $this->objectClassContact() => $this->contactModel(),
+ $this->objectClassPerson() => $this->userModel(),
+ $this->objectClassGroup() => $this->groupModel(),
+ $this->objectClassContainer() => $this->containerModel(),
+ $this->objectClassPrinter() => $this->printerModel(),
+ $this->objectClassOrganization() => $this->organizationModel(),
+ $this->objectClassOu() => $this->organizationalUnitModel(),
+ $this->objectClassForeignSecurityPrincipal() => $this->foreignSecurityPrincipalModel(),
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectSid()
+ {
+ return 'objectsid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function objectSidRequiresConversion()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function operatingSystem()
+ {
+ return 'operatingsystem';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function operatingSystemServicePack()
+ {
+ return 'operatingsystemservicepack';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function operatingSystemVersion()
+ {
+ return 'operatingsystemversion';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function organization()
+ {
+ return 'organization';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function organizationName()
+ {
+ return 'o';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function organizationalPerson()
+ {
+ return 'organizationalperson';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function organizationalUnit()
+ {
+ return 'organizationalunit';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function organizationalUnitModel()
+ {
+ return OrganizationalUnit::class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function organizationModel()
+ {
+ return Organization::class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function organizationalUnitShort()
+ {
+ return 'ou';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function otherMailbox()
+ {
+ return 'othermailbox';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function passwordLastSet()
+ {
+ return 'pwdlastset';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function person()
+ {
+ return 'person';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function personalTitle()
+ {
+ return 'personaltitle';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function physicalDeliveryOfficeName()
+ {
+ return 'physicaldeliveryofficename';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function portName()
+ {
+ return 'portname';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function postalCode()
+ {
+ return 'postalcode';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function postOfficeBox()
+ {
+ return 'postofficebox';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function primaryGroupId()
+ {
+ return 'primarygroupid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerBinNames()
+ {
+ return 'printbinnames';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerColorSupported()
+ {
+ return 'printcolor';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerDuplexSupported()
+ {
+ return 'printduplexsupported';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerEndTime()
+ {
+ return 'printendtime';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerMaxResolutionSupported()
+ {
+ return 'printmaxresolutionsupported';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerMediaSupported()
+ {
+ return 'printmediasupported';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerMemory()
+ {
+ return 'printmemory';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerModel()
+ {
+ return Printer::class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerName()
+ {
+ return 'printername';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerOrientationSupported()
+ {
+ return 'printorientationssupported';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerPrintRate()
+ {
+ return 'printrate';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerPrintRateUnit()
+ {
+ return 'printrateunit';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerShareName()
+ {
+ return 'printsharename';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerStaplingSupported()
+ {
+ return 'printstaplingsupported';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function printerStartTime()
+ {
+ return 'printstarttime';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function priority()
+ {
+ return 'priority';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function profilePath()
+ {
+ return 'profilepath';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function proxyAddresses()
+ {
+ return 'proxyaddresses';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function roomNumber()
+ {
+ return 'roomnumber';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rootDomainNamingContext()
+ {
+ return 'rootdomainnamingcontext';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function schemaNamingContext()
+ {
+ return 'schemanamingcontext';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function scriptPath()
+ {
+ return 'scriptpath';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function serialNumber()
+ {
+ return 'serialnumber';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function serverName()
+ {
+ return 'servername';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function showInAddressBook()
+ {
+ return 'showinaddressbook';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function street()
+ {
+ return 'street';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function streetAddress()
+ {
+ return 'streetaddress';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function systemFlags()
+ {
+ return 'systemflags';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function telephone()
+ {
+ return 'telephonenumber';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function mobile()
+ {
+ return 'mobile';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function otherMobile()
+ {
+ return 'othermobile';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function facsimile()
+ {
+ return 'facsimiletelephonenumber';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function thumbnail()
+ {
+ return 'thumbnailphoto';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function title()
+ {
+ return 'title';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function top()
+ {
+ return 'top';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function true()
+ {
+ return 'TRUE';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function unicodePassword()
+ {
+ return 'unicodepwd';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function updatedAt()
+ {
+ return 'whenchanged';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function url()
+ {
+ return 'url';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function user()
+ {
+ return 'user';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function userAccountControl()
+ {
+ return 'useraccountcontrol';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function userId()
+ {
+ return 'uid';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function userModel()
+ {
+ return User::class;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function userObjectClasses(): array
+ {
+ return [
+ $this->top(),
+ $this->person(),
+ $this->organizationalPerson(),
+ $this->objectClassUser(),
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function userPrincipalName()
+ {
+ return 'userprincipalname';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function userWorkstations()
+ {
+ return 'userworkstations';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function versionNumber()
+ {
+ return 'versionnumber';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function foreignSecurityPrincipalModel()
+ {
+ return ForeignSecurityPrincipal::class;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/SchemaInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/SchemaInterface.php
new file mode 100644
index 0000000..023df74
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Schemas/SchemaInterface.php
@@ -0,0 +1,1421 @@
+<?php
+
+namespace Adldap\Schemas;
+
+interface SchemaInterface
+{
+ /**
+ * The date when the account expires. This value represents the number of 100-nanosecond
+ * intervals since January 1, 1601 (UTC). A value of 0 or 0x7FFFFFFFFFFFFFFF
+ * (9223372036854775807) indicates that the account never expires.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675098(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function accountExpires();
+
+ /**
+ * The logon name used to support clients and servers running earlier versions of the
+ * operating system, such as Windows NT 4.0, Windows 95, Windows 98,
+ * and LAN Manager. This attribute must be 20 characters or
+ * less to support earlier clients.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679635(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function accountName();
+
+ /**
+ * This attribute contains information about every account type object.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679637(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function accountType();
+
+ /**
+ * The name to be displayed on admin screens.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675214(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function adminDisplayName();
+
+ /**
+ * Ambiguous name resolution attribute to be used when choosing between objects.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675223(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function anr();
+
+ /**
+ * The number of times the user tried to log on to the account using
+ * an incorrect password. A value of 0 indicates that the
+ * value is unknown.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675244(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function badPasswordCount();
+
+ /**
+ * The last time and date that an attempt to log on to this
+ * account was made with a password that is not valid.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675243(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function badPasswordTime();
+
+ /**
+ * The name that represents an object.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675449(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function commonName();
+
+ /**
+ * The user's company name.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675457(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function company();
+
+ /**
+ * The object class computer string.
+ *
+ * Used when constructing new Computer models.
+ *
+ * @return string
+ */
+ public function computer();
+
+ /**
+ * The class name of the Computer model.
+ *
+ * @return string
+ */
+ public function computerModel();
+
+ /**
+ * DN enterprise configuration naming context.
+ *
+ * @link https://support.microsoft.com/en-us/kb/219005
+ *
+ * @return string
+ */
+ public function configurationNamingContext();
+
+ /**
+ * The object class contact string.
+ *
+ * Used when constructing new User models.
+ *
+ * @return string
+ */
+ public function contact();
+
+ /**
+ * The class name of the Contact model.
+ *
+ * @return string
+ */
+ public function contactModel();
+
+ /**
+ * The class name of the Container model.
+ *
+ * @return string
+ */
+ public function containerModel();
+
+ /**
+ * The entry's country attribute.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675432(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function country();
+
+ /**
+ * The entry's created at attribute.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680924(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function createdAt();
+
+ /**
+ * The entry's current time attribute.
+ *
+ * This attribute is only available with the Root DSE record.
+ *
+ * @return string
+ */
+ public function currentTime();
+
+ /**
+ * This is the default NC for a particular server.
+ *
+ * By default, the DN for the domain of which this directory server is a member.
+ *
+ * @link https://support.microsoft.com/en-us/kb/219005
+ *
+ * @return string
+ */
+ public function defaultNamingContext();
+
+ /**
+ * Contains the name for the department in which the user works.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675490(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function department();
+
+ /**
+ * Identifies a department within an organization.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675491(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function departmentNumber();
+
+ /**
+ * Contains the description to display for an object. This value is restricted
+ * as single-valued for backward compatibility in some cases but
+ * is allowed to be multi-valued in others.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675492(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function description();
+
+ /**
+ * The display name for an object. This is usually the combination
+ * of the users first name, middle initial, and last name.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675514(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function displayName();
+
+ /**
+ * The LDAP API references an LDAP object by its distinguished name (DN).
+ *
+ * A DN is a sequence of relative distinguished names (RDN) connected by commas.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/aa366101(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function distinguishedName();
+
+ /**
+ * The LDAP API references an LDAP object by its distinguished name (DN).
+ *
+ * Different vendors expect the value of the distinguished name to be in
+ * different places. For example ActiveDirectory expects distinguishedname
+ * value to be the first element in an array, however OpenLDAP expects
+ * the dn attribute to contain the value, not an array.
+ *
+ * @deprecated since 10.0.0
+ *
+ * @return int|null
+ */
+ public function distinguishedNameSubKey();
+
+ /**
+ * Name of computer as registered in DNS.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675524(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function dnsHostName();
+
+ /**
+ * Domain Component located inside an RDN.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/aa366101(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function domainComponent();
+
+ /**
+ * The device driver name.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675652(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function driverName();
+
+ /**
+ * The Version number of device driver.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675653(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function driverVersion();
+
+ /**
+ * The list of email addresses for a contact.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676855(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function email();
+
+ /**
+ * The email nickname for the user.
+ *
+ * @return string
+ */
+ public function emailNickname();
+
+ /**
+ * The ID of an employee.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675662(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function employeeId();
+
+ /**
+ * The number assigned to an employee other than the ID.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675663(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function employeeNumber();
+
+ /**
+ * The job category for an employee.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675664(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function employeeType();
+
+ /**
+ * The class name of the Entry model.
+ *
+ * @return string
+ */
+ public function entryModel();
+
+ /**
+ * The LDAP `false` boolean in string form for conversion.
+ *
+ * @return string
+ */
+ public function false();
+
+ /**
+ * The LDAP filter to query for enabled users.
+ *
+ * @return mixed
+ */
+ public function filterEnabled();
+
+ /**
+ * The LDAP filter to query for disabled users.
+ *
+ * @return mixed
+ */
+ public function filterDisabled();
+
+ /**
+ * Contains the given name (first name) of the user.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675719(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function firstName();
+
+ /**
+ * The class name of the Group model.
+ *
+ * @return string
+ */
+ public function groupModel();
+
+ /**
+ * Contains a set of flags that define the type and scope of a group object.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms675935(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function groupType();
+
+ /**
+ * A user's home address.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676193(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function homeAddress();
+
+ /**
+ * The users mailbox database location.
+ *
+ * @return string
+ */
+ public function homeMdb();
+
+ /**
+ * Specifies the drive letter to which to map the UNC path specified by homeDirectory.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676191(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function homeDrive();
+
+ /**
+ * The home directory for the account.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676190(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function homeDirectory();
+
+ /**
+ * The user's main home phone number.
+ *
+ * @link https://docs.microsoft.com/en-us/windows/desktop/ADSchema/a-homephone
+ *
+ * @return string|null
+ */
+ public function homePhone();
+
+ /**
+ * The users extra notable information.
+ *
+ * @return string
+ */
+ public function info();
+
+ /**
+ * Contains the initials for parts of the user's full name.
+ *
+ * This may be used as the middle initial in the Windows Address Book.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676202(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function initials();
+
+ /**
+ * A bitfield that dictates how the object is instantiated on a particular server.
+ *
+ * The value of this attribute can differ on different replicas even if the replicas are in sync.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676204(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function instanceType();
+
+ /**
+ * Specifies the TCP/IP address for the phone. Used by telephony.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/cc221092.aspx
+ *
+ * @return string
+ */
+ public function ipPhone();
+
+ /**
+ * If TRUE, the object hosting this attribute must be replicated during installation of a new replica.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676798(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function isCriticalSystemObject();
+
+ /**
+ * Used to store one or more images of a person using the JPEG File Interchange Format [JFIF].
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676813(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function jpegPhoto();
+
+ /**
+ * This attribute is not used.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676822(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function lastLogOff();
+
+ /**
+ * The last time the user logged on. This value is stored as a large integer that
+ * represents the number of 100-nanosecond intervals since January 1, 1601 (UTC).
+ *
+ * A value of zero means that the last logon time is unknown.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676823(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function lastLogOn();
+
+ /**
+ * This is the time that the user last logged into the domain.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676824(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function lastLogOnTimestamp();
+
+ /**
+ * This attribute contains the family or last name for a user.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679872(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function lastName();
+
+ /**
+ * The distinguished name previously used by Exchange.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676830(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function legacyExchangeDn();
+
+ /**
+ * The users locale.
+ *
+ * @return string
+ */
+ public function locale();
+
+ /**
+ * The user's location, such as office number.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676839(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function location();
+
+ /**
+ * The date and time (UTC) that this account was locked out. This value is stored
+ * as a large integer that represents the number of 100-nanosecond intervals
+ * since January 1, 1601 (UTC). A value of zero means that the
+ * account is not currently locked out.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676843(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function lockoutTime();
+
+ /**
+ * Contains the distinguished name of the user who is the user's manager.
+ *
+ * The manager's user object contains a directReports property that
+ * contains references to all user objects that have their manager
+ * properties set to this distinguished name.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676859(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function manager();
+
+ /**
+ * The distinguished name of the user that is assigned to manage this object.
+ *
+ * @link https://docs.microsoft.com/en-us/windows/desktop/adschema/a-managedby
+ *
+ * @return string
+ */
+ public function managedBy();
+
+ /**
+ * The maximum amount of time, in 100-nanosecond intervals, a password is valid.
+ *
+ * This value is stored as a large integer that represents the number of
+ * 100-nanosecond intervals from the time the password was set
+ * before the password expires.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms676863(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function maxPasswordAge();
+
+ /**
+ * The list of users that belong to the group.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms677097(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function member();
+
+ /**
+ * The identifier of records that belong to a group.
+ *
+ * For example, in ActiveDirectory, the 'member' attribute on
+ * a group record contains a list of distinguished names,
+ * so `distinguishedname` would be the identifier.
+ *
+ * In other environments such as Sun Directory
+ * Server, this identifier would be `uid`.
+ *
+ * @return string
+ */
+ public function memberIdentifier();
+
+ /**
+ * The distinguished names of the groups to which this object belongs.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms677099(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function memberOf();
+
+ /**
+ * The distinguished names of the groups to which this object belongs.
+ *
+ * This string contains a rule OID indicating the inclusion of ancestral and child members.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms677099(v=vs.85).aspx
+ * @link https://msdn.microsoft.com/en-us/library/aa746475(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function memberOfRecursive();
+
+ /**
+ * The range limited list of users that belong to the group. See range limit in Active Directory
+ * (Range Retrieval of Attribute Values https://msdn.microsoft.com/en-us/library/cc223242.aspx)
+ * Issue #342.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms677097(v=vs.85).aspx
+ *
+ * @param string|int $from
+ * @param string|int $to
+ *
+ * @return string
+ */
+ public function memberRange($from, $to);
+
+ /**
+ * @link https://msdn.microsoft.com/en-us/library/ms981934(v=exchg.65).aspx
+ *
+ * @return string
+ */
+ public function messageTrackingEnabled();
+
+ /**
+ * The object category of an exchange server.
+ *
+ * @return string
+ */
+ public function msExchangeServer();
+
+ /**
+ * The general name of the entry.
+ *
+ * @return string
+ */
+ public function name();
+
+ /**
+ * Returns a string value indicating that an account does not expire.
+ *
+ * @return string
+ */
+ public function neverExpiresDate();
+
+ /**
+ * An object class name used to group objects of this or derived classes.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679011(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function objectCategory();
+
+ /**
+ * The computer object category.
+ *
+ * @return string
+ */
+ public function objectCategoryComputer();
+
+ /**
+ * The container object category.
+ *
+ * @return string
+ */
+ public function objectCategoryContainer();
+
+ /**
+ * The exchange private MDB category.
+ *
+ * @return string
+ */
+ public function objectCategoryExchangePrivateMdb();
+
+ /**
+ * The exchange server object category.
+ *
+ * @return string
+ */
+ public function objectCategoryExchangeServer();
+
+ /**
+ * The exchange storage group object category.
+ *
+ * @return string
+ */
+ public function objectCategoryExchangeStorageGroup();
+
+ /**
+ * The group object category.
+ *
+ * @return string
+ */
+ public function objectCategoryGroup();
+
+ /**
+ * The organizational unit category.
+ *
+ * @return string
+ */
+ public function objectCategoryOrganizationalUnit();
+
+ /**
+ * The person object category.
+ *
+ * @return string
+ */
+ public function objectCategoryPerson();
+
+ /**
+ * The printer object category.
+ *
+ * @return string
+ */
+ public function objectCategoryPrinter();
+
+ /**
+ * The list of classes from which this class is derived.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679012(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function objectClass();
+
+ /**
+ * The computer object class.
+ *
+ * @return string
+ */
+ public function objectClassComputer();
+
+ /**
+ * The contact object class.
+ *
+ * @return string
+ */
+ public function objectClassContact();
+
+ /**
+ * The container object class.
+ *
+ * @return string
+ */
+ public function objectClassContainer();
+
+ /**
+ * The group object class.
+ *
+ * @return string
+ */
+ public function objectClassGroup();
+
+ /**
+ * The ou object class.
+ *
+ * @return string
+ */
+ public function objectClassOu();
+
+ /**
+ * The person object class.
+ *
+ * Represents people who are associated with an organization in some way.
+ *
+ * @return string
+ */
+ public function objectClassPerson();
+
+ /**
+ * The printer object class.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms683911(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function objectClassPrinter();
+
+ /**
+ * The user object class.
+ *
+ * @return string
+ */
+ public function objectClassUser();
+
+ /**
+ * The object class model map.
+ *
+ * @return array
+ */
+ public function objectClassModelMap();
+
+ /**
+ * The unique identifier for an object.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679021(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function objectGuid();
+
+ /**
+ * Determine whether the object GUID requires conversion from binary.
+ *
+ * @return bool
+ */
+ public function objectGuidRequiresConversion();
+
+ /**
+ * A binary value that specifies the security identifier (SID) of the user.
+ *
+ * The SID is a unique value used to identify the user as a security principal.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679024(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function objectSid();
+
+ /**
+ * Determine whether the object SID requires conversion from binary.
+ *
+ * @return bool
+ */
+ public function objectSidRequiresConversion();
+
+ /**
+ * The Operating System name, for example, Windows Vista Enterprise.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679076(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function operatingSystem();
+
+ /**
+ * The operating system service pack ID string (for example, SP3).
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679078(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function operatingSystemServicePack();
+
+ /**
+ * The operating system version string, for example, 4.0.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679079(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function operatingSystemVersion();
+
+ /**
+ * The RDN version of organization name for use in distinguished names.
+ *
+ * @return mixed
+ */
+ public function organizationName();
+
+ /**
+ * This class is used for objects that contain organizational information about a user,
+ * such as the employee number, department, manager, title, office address, and so on.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms683883(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function organizationalPerson();
+
+ /**
+ * A container for storing users, computers, and other account objects.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms683886(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function organizationalUnit();
+
+ /**
+ * The class name of the Organizational Unit model.
+ *
+ * @return string
+ */
+ public function organizationalUnitModel();
+
+ /**
+ * The RDN version of organizational unit for use in distinguished names.
+ *
+ * @return string
+ */
+ public function organizationalUnitShort();
+
+ /**
+ * Contains other additional mail addresses in a form such as CCMAIL: JohnDoe.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679091(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function otherMailbox();
+
+ /**
+ * The date and time that the password for this account was last changed.
+ *
+ * This value is stored as a large integer that represents the number of 100 nanosecond intervals
+ * since January 1, 1601 (UTC). If this value is set to 0 and the User-Account-Control attribute
+ * does not contain the UF_DONT_EXPIRE_PASSWD flag, then the user must set the password at
+ * the next logon.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679430(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function passwordLastSet();
+
+ /**
+ * The person object class.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms683895(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function person();
+
+ /**
+ * The user's title.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679115(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function personalTitle();
+
+ /**
+ * Contains the office location in the user's place of business.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679117(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function physicalDeliveryOfficeName();
+
+ /**
+ * List of port names. For example, for printer ports or comm ports.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679131(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function portName();
+
+ /**
+ * The postal or zip code for mail delivery.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679366(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function postalCode();
+
+ /**
+ * The post office box number for this object.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679367(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function postOfficeBox();
+
+ /**
+ * Contains the relative identifier (RID) for the primary group of the user.
+ *
+ * By default, this is the RID for the Domain Users group.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679375(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function primaryGroupId();
+
+ /**
+ * A list of printer bin names.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679380(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerBinNames();
+
+ /**
+ * If a printer can print in color.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679382(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerColorSupported();
+
+ /**
+ * Indicates the type of duplex support a printer has.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679383(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerDuplexSupported();
+
+ /**
+ * The time a print queue stops servicing jobs.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679384(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerEndTime();
+
+ /**
+ * The maximum printer resolution.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679391(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerMaxResolutionSupported();
+
+ /**
+ * A list of media supported by a printer.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679395(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerMediaSupported();
+
+ /**
+ * The amount of memory installed in a printer.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679396(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerMemory();
+
+ /**
+ * The class name of the Printer model.
+ *
+ * @return string
+ */
+ public function printerModel();
+
+ /**
+ * The display name of an attached printer.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679385(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerName();
+
+ /**
+ * The page rotation for landscape printing.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679402(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerOrientationSupported();
+
+ /**
+ * Driver-supplied print rate.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679405(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerPrintRate();
+
+ /**
+ * Driver-supplied print rate unit.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679406(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerPrintRateUnit();
+
+ /**
+ * The printer's share name.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679408(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerShareName();
+
+ /**
+ * If the printer supports stapling. Supplied by the driver.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679410(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerStaplingSupported();
+
+ /**
+ * The time a print queue begins servicing jobs.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679411(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function printerStartTime();
+
+ /**
+ * The current priority (of a process, print job, and so on).
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679413(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function priority();
+
+ /**
+ * Specifies a path to the user's profile. This value can be a null
+ * string, a local absolute path, or a UNC path.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679422(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function profilePath();
+
+ /**
+ * A proxy address is the address by which a Microsoft Exchange Server recipient
+ * object is recognized in a foreign mail system. Proxy addresses are required
+ * for all recipient objects, such as custom recipients and distribution lists.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679424(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function proxyAddresses();
+
+ /**
+ * The room number of an object.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679615(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function roomNumber();
+
+ /**
+ * The DN of the root domain NC for this DC's forest.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/cc223262.aspx
+ *
+ * @return mixed
+ */
+ public function rootDomainNamingContext();
+
+ /**
+ * The attribute.
+ *
+ * @return mixed
+ */
+ public function schemaNamingContext();
+
+ /**
+ * This attribute specifies the path for the user's logon script. The string can be null.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679656(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function scriptPath();
+
+ /**
+ * Part of X.500 specification. Not used by Active Directory.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679771(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function serialNumber();
+
+ /**
+ * The name of a server.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679772(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function serverName();
+
+ /**
+ * This attribute is used to indicate in which MAPI address books an object will appear.
+ *
+ * It is usually maintained by the Exchange Recipient Update Service.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679822(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function showInAddressBook();
+
+ /**
+ * The street address.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679882(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function street();
+
+ /**
+ * The street address.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms679882(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function streetAddress();
+
+ /**
+ * An integer value that contains flags that define additional properties of the class.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680022(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function systemFlags();
+
+ /**
+ * The primary telephone number.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680027(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function telephone();
+
+ /**
+ * The primary mobile phone number.
+ *
+ * @link https://docs.microsoft.com/en-us/windows/desktop/adschema/a-mobile
+ *
+ * @return string
+ */
+ public function mobile();
+
+ /**
+ * The secondary mobile phone number.
+ *
+ * @link https://docs.microsoft.com/en-us/windows/desktop/ADSchema/a-othermobile
+ *
+ * @return string
+ */
+ public function otherMobile();
+
+ /**
+ * The users thumbnail photo path.
+ *
+ * @return string
+ */
+ public function thumbnail();
+
+ /**
+ * Contains the user's job title.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680037(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function title();
+
+ /**
+ * The top level class from which all classes are derived.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms683975(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function top();
+
+ /**
+ * The LDAP `true` boolean in string form for conversion.
+ *
+ * @return string
+ */
+ public function true();
+
+ /**
+ * The password of the user in Windows NT one-way format (OWF). Windows 2000 uses the Windows NT OWF.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680513(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function unicodePassword();
+
+ /**
+ * The date when this object was last changed.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680921(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function updatedAt();
+
+ /**
+ * The entry's URL attribute.
+ *
+ * @return string
+ */
+ public function url();
+
+ /**
+ * The user object class.
+ *
+ * This class is used to store information about an employee or contractor who works for an organization.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms683980(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function user();
+
+ /**
+ * Flags that control the behavior of the user account.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680832(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function userAccountControl();
+
+ /**
+ * The user ID attribute.
+ *
+ * @return string
+ */
+ public function userId();
+
+ /**
+ * The class name of the User model.
+ *
+ * @return string
+ */
+ public function userModel();
+
+ /**
+ * The object classes that User models must be constructed with.
+ *
+ * @return array
+ */
+ public function userObjectClasses(): array;
+
+ /**
+ * This attribute contains the UPN that is an Internet-style login name for
+ * a user based on the Internet standard RFC 822.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680857(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function userPrincipalName();
+
+ /**
+ * Contains the NetBIOS or DNS names of the computers running Windows NT Workstation
+ * or Windows 2000 Professional from which the user can log on.
+ *
+ * Each NetBIOS name is separated by a comma.
+ *
+ * Multiple names should be separated by commas.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680868(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function userWorkstations();
+
+ /**
+ * A general purpose version number.
+ *
+ * @link https://msdn.microsoft.com/en-us/library/ms680897(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function versionNumber();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Utilities.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Utilities.php
new file mode 100644
index 0000000..1c70e8c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/adldap2/adldap2/src/Utilities.php
@@ -0,0 +1,232 @@
+<?php
+
+namespace Adldap;
+
+class Utilities
+{
+ /**
+ * Converts a DN string into an array of RDNs.
+ *
+ * This will also decode hex characters into their true
+ * UTF-8 representation embedded inside the DN as well.
+ *
+ * @param string $dn
+ * @param bool $removeAttributePrefixes
+ *
+ * @return array|false
+ */
+ public static function explodeDn($dn, $removeAttributePrefixes = true)
+ {
+ $dn = ldap_explode_dn($dn, ($removeAttributePrefixes ? 1 : 0));
+
+ if (is_array($dn) && array_key_exists('count', $dn)) {
+ foreach ($dn as $rdn => $value) {
+ $dn[$rdn] = self::unescape($value);
+ }
+ }
+
+ return $dn;
+ }
+
+ /**
+ * Un-escapes a hexadecimal string into
+ * its original string representation.
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ public static function unescape($value)
+ {
+ return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function ($matches) {
+ return chr(hexdec($matches[1]));
+ }, $value);
+ }
+
+ /**
+ * Convert a binary SID to a string SID.
+ *
+ * @author Chad Sikorra
+ *
+ * @link https://github.com/ChadSikorra
+ * @link https://stackoverflow.com/questions/39533560/php-ldap-get-user-sid
+ *
+ * @param string $value The Binary SID
+ *
+ * @return string|null
+ */
+ public static function binarySidToString($value)
+ {
+ // Revision - 8bit unsigned int (C1)
+ // Count - 8bit unsigned int (C1)
+ // 2 null bytes
+ // ID - 32bit unsigned long, big-endian order
+ $sid = @unpack('C1rev/C1count/x2/N1id', $value);
+
+ if (!isset($sid['id']) || !isset($sid['rev'])) {
+ return;
+ }
+
+ $revisionLevel = $sid['rev'];
+
+ $identifierAuthority = $sid['id'];
+
+ $subs = isset($sid['count']) ? $sid['count'] : 0;
+
+ $sidHex = $subs ? bin2hex($value) : '';
+
+ $subAuthorities = [];
+
+ // The sub-authorities depend on the count, so only get as
+ // many as the count, regardless of data beyond it.
+ for ($i = 0; $i < $subs; $i++) {
+ $data = implode('', array_reverse(
+ str_split(
+ substr($sidHex, 16 + ($i * 8), 8),
+ 2
+ )
+ ));
+
+ $subAuthorities[] = hexdec($data);
+ }
+
+ // Tack on the 'S-' and glue it all together...
+ return 'S-'.$revisionLevel.'-'.$identifierAuthority.implode(
+ preg_filter('/^/', '-', $subAuthorities)
+ );
+ }
+
+ /**
+ * Convert a binary GUID to a string GUID.
+ *
+ * @param string $binGuid
+ *
+ * @return string|null
+ */
+ public static function binaryGuidToString($binGuid)
+ {
+ if (trim($binGuid) == '' || is_null($binGuid)) {
+ return;
+ }
+
+ $hex = unpack('H*hex', $binGuid)['hex'];
+
+ $hex1 = substr($hex, -26, 2).substr($hex, -28, 2).substr($hex, -30, 2).substr($hex, -32, 2);
+ $hex2 = substr($hex, -22, 2).substr($hex, -24, 2);
+ $hex3 = substr($hex, -18, 2).substr($hex, -20, 2);
+ $hex4 = substr($hex, -16, 4);
+ $hex5 = substr($hex, -12, 12);
+
+ $guid = sprintf('%s-%s-%s-%s-%s', $hex1, $hex2, $hex3, $hex4, $hex5);
+
+ return $guid;
+ }
+
+ /**
+ * Converts a string GUID to it's hex variant.
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ public static function stringGuidToHex($string)
+ {
+ $hex = '\\'.substr($string, 6, 2).'\\'.substr($string, 4, 2).'\\'.substr($string, 2, 2).'\\'.substr($string, 0, 2);
+ $hex = $hex.'\\'.substr($string, 11, 2).'\\'.substr($string, 9, 2);
+ $hex = $hex.'\\'.substr($string, 16, 2).'\\'.substr($string, 14, 2);
+ $hex = $hex.'\\'.substr($string, 19, 2).'\\'.substr($string, 21, 2);
+ $hex = $hex.'\\'.substr($string, 24, 2).'\\'.substr($string, 26, 2).'\\'.substr($string, 28, 2).'\\'.substr($string, 30, 2).'\\'.substr($string, 32, 2).'\\'.substr($string, 34, 2);
+
+ return $hex;
+ }
+
+ /**
+ * Encode a password for transmission over LDAP.
+ *
+ * @param string $password The password to encode
+ *
+ * @return string
+ */
+ public static function encodePassword($password)
+ {
+ return iconv('UTF-8', 'UTF-16LE', '"'.$password.'"');
+ }
+
+ /**
+ * Salt and hash a password to make its SSHA OpenLDAP version.
+ *
+ * @param string $password The password to create
+ *
+ * @return string
+ */
+ public static function makeSSHAPassword($password)
+ {
+ mt_srand((float) microtime() * 1000000);
+ $salt = pack('CCCC', mt_rand(), mt_rand(), mt_rand(), mt_rand());
+
+ return '{SSHA}'.base64_encode(pack('H*', sha1($password.$salt)).$salt);
+ }
+
+ /**
+ * Round a Windows timestamp down to seconds and remove
+ * the seconds between 1601-01-01 and 1970-01-01.
+ *
+ * @param float $windowsTime
+ *
+ * @return float
+ */
+ public static function convertWindowsTimeToUnixTime($windowsTime)
+ {
+ return round($windowsTime / 10000000) - 11644473600;
+ }
+
+ /**
+ * Convert a Unix timestamp to Windows timestamp.
+ *
+ * @param float $unixTime
+ *
+ * @return float
+ */
+ public static function convertUnixTimeToWindowsTime($unixTime)
+ {
+ return ($unixTime + 11644473600) * 10000000;
+ }
+
+ /**
+ * Validates that the inserted string is an object SID.
+ *
+ * @param string $sid
+ *
+ * @return bool
+ */
+ public static function isValidSid($sid)
+ {
+ return (bool) preg_match("/^S-\d(-\d{1,10}){1,16}$/i", $sid);
+ }
+
+ /**
+ * Validates that the inserted string is an object GUID.
+ *
+ * @param string $guid
+ *
+ * @return bool
+ */
+ public static function isValidGuid($guid)
+ {
+ return (bool) preg_match('/^([0-9a-fA-F]){8}(-([0-9a-fA-F]){4}){3}-([0-9a-fA-F]){12}$|^([0-9a-fA-F]{8}-){3}[0-9a-fA-F]{8}$/', $guid);
+ }
+
+ /**
+ * Converts an ignore string into an array.
+ *
+ * @param string $ignore
+ *
+ * @return array
+ */
+ protected static function ignoreStrToArray($ignore)
+ {
+ $ignore = trim($ignore);
+
+ return $ignore ? str_split($ignore) : [];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/bin/carbon b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/bin/carbon
new file mode 120000
index 0000000..0da4804
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/bin/carbon
@@ -0,0 +1 @@
+../nesbot/carbon/bin/carbon
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/bin/var-dump-server b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/bin/var-dump-server
new file mode 120000
index 0000000..6bd4e93
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/bin/var-dump-server
@@ -0,0 +1 @@
+../symfony/var-dumper/Resources/bin/var-dump-server
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/ClassLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/ClassLoader.php
index 1a58957..6d0c3f2 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/ClassLoader.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/ClassLoader.php
@@ -42,6 +42,8 @@
*/
class ClassLoader
{
+ private $vendorDir;
+
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
@@ -57,6 +59,13 @@
private $missingClasses = array();
private $apcuPrefix;
+ private static $registeredLoaders = array();
+
+ public function __construct($vendorDir = null)
+ {
+ $this->vendorDir = $vendorDir;
+ }
+
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
@@ -300,6 +309,17 @@
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+
+ if (null === $this->vendorDir) {
+ return;
+ }
+
+ if ($prepend) {
+ self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
+ } else {
+ unset(self::$registeredLoaders[$this->vendorDir]);
+ self::$registeredLoaders[$this->vendorDir] = $this;
+ }
}
/**
@@ -308,13 +328,17 @@
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
+
+ if (null !== $this->vendorDir) {
+ unset(self::$registeredLoaders[$this->vendorDir]);
+ }
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
- * @return bool|null True if loaded, null otherwise
+ * @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
@@ -323,6 +347,8 @@
return true;
}
+
+ return null;
}
/**
@@ -367,6 +393,16 @@
return $file;
}
+ /**
+ * Returns the currently registered loaders indexed by their corresponding vendor directories.
+ *
+ * @return self[]
+ */
+ public static function getRegisteredLoaders()
+ {
+ return self::$registeredLoaders;
+ }
+
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/InstalledVersions.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/InstalledVersions.php
index 2d16727..b3a4e16 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/InstalledVersions.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/InstalledVersions.php
@@ -1,332 +1,337 @@
<?php
-
-
-
-
-
-
-
-
-
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
namespace Composer;
+use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
-
-
-
-
-
+/**
+ * This class is copied in every Composer installed project and available to all
+ *
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
+ *
+ * To require it's presence, you can require `composer-runtime-api ^2.0`
+ */
class InstalledVersions
{
-private static $installed = array (
- 'root' =>
- array (
- 'pretty_version' => '1.0.0+no-version-set',
- 'version' => '1.0.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => NULL,
- 'name' => '__root__',
- ),
- 'versions' =>
- array (
- '__root__' =>
- array (
- 'pretty_version' => '1.0.0+no-version-set',
- 'version' => '1.0.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => NULL,
- ),
- 'bshaffer/oauth2-server-php' =>
- array (
- 'pretty_version' => 'v1.11.1',
- 'version' => '1.11.1.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
- ),
- 'ddeboer/imap' =>
- array (
- 'pretty_version' => '1.11.0',
- 'version' => '1.11.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => 'a089dfcb9d177f921eb5dadc8d4144a44dff22ee',
- ),
- 'exorus/php-mime-mail-parser' =>
- array (
- 'replaced' =>
- array (
- 0 => '*',
- ),
- ),
- 'matthiasmullie/minify' =>
- array (
- 'pretty_version' => '1.3.65',
- 'version' => '1.3.65.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '227f19062451c55a797e0cc667ef983834e6580c',
- ),
- 'matthiasmullie/path-converter' =>
- array (
- 'pretty_version' => '1.1.3',
- 'version' => '1.1.3.0',
- 'aliases' =>
- array (
- ),
- 'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
- ),
- 'messaged/php-mime-mail-parser' =>
- array (
- 'replaced' =>
- array (
- 0 => '*',
- ),
- ),
- 'mustangostang/spyc' =>
- array (
- 'pretty_version' => '0.6.3',
- 'version' => '0.6.3.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '4627c838b16550b666d15aeae1e5289dd5b77da0',
- ),
- 'paragonie/random_compat' =>
- array (
- 'pretty_version' => 'v9.99.100',
- 'version' => '9.99.100.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
- ),
- 'php-mime-mail-parser/php-mime-mail-parser' =>
- array (
- 'pretty_version' => '5.0.5',
- 'version' => '5.0.5.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '27983433aabeccee832573c3c56e6a4855e57745',
- ),
- 'phpmailer/phpmailer' =>
- array (
- 'pretty_version' => 'v6.2.0',
- 'version' => '6.2.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => 'e38888a75c070304ca5514197d4847a59a5c853f',
- ),
- 'robthree/twofactorauth' =>
- array (
- 'pretty_version' => '1.7.0',
- 'version' => '1.7.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '37983bf675c5baca09d19d6705170489d0df0002',
- ),
- 'soundasleep/html2text' =>
- array (
- 'pretty_version' => '0.5.0',
- 'version' => '0.5.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
- ),
- 'yubico/u2flib-server' =>
- array (
- 'pretty_version' => '1.0.2',
- 'version' => '1.0.2.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '55d813acf68212ad2cadecde07551600d6971939',
- ),
- ),
-);
+ private static $installed;
+ private static $canGetVendors;
+ private static $installedByVendor = array();
+ /**
+ * Returns a list of all package names which are present, either by being installed, replaced or provided
+ *
+ * @return string[]
+ * @psalm-return list<string>
+ */
+ public static function getInstalledPackages()
+ {
+ $packages = array();
+ foreach (self::getInstalled() as $installed) {
+ $packages[] = array_keys($installed['versions']);
+ }
+ if (1 === \count($packages)) {
+ return $packages[0];
+ }
+ return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
+ }
+ /**
+ * Returns a list of all package names with a specific type e.g. 'library'
+ *
+ * @param string $type
+ * @return string[]
+ * @psalm-return list<string>
+ */
+ public static function getInstalledPackagesByType($type)
+ {
+ $packagesByType = array();
+ foreach (self::getInstalled() as $installed) {
+ foreach ($installed['versions'] as $name => $package) {
+ if (isset($package['type']) && $package['type'] === $type) {
+ $packagesByType[] = $name;
+ }
+ }
+ }
+ return $packagesByType;
+ }
-public static function getInstalledPackages()
-{
-return array_keys(self::$installed['versions']);
-}
+ /**
+ * Checks whether the given package is installed
+ *
+ * This also returns true if the package name is provided or replaced by another package
+ *
+ * @param string $packageName
+ * @param bool $includeDevRequirements
+ * @return bool
+ */
+ public static function isInstalled($packageName, $includeDevRequirements = true)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (isset($installed['versions'][$packageName])) {
+ return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
+ }
+ }
+ return false;
+ }
+ /**
+ * Checks whether the given package satisfies a version constraint
+ *
+ * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
+ *
+ * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
+ *
+ * @param VersionParser $parser Install composer/semver to have access to this class and functionality
+ * @param string $packageName
+ * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
+ * @return bool
+ */
+ public static function satisfies(VersionParser $parser, $packageName, $constraint)
+ {
+ $constraint = $parser->parseConstraints($constraint);
+ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+ return $provided->matches($constraint);
+ }
+ /**
+ * Returns a version constraint representing all the range(s) which are installed for a given package
+ *
+ * It is easier to use this via isInstalled() with the $constraint argument if you need to check
+ * whether a given version of a package is installed, and not just whether it exists
+ *
+ * @param string $packageName
+ * @return string Version constraint usable with composer/semver
+ */
+ public static function getVersionRanges($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+ $ranges = array();
+ if (isset($installed['versions'][$packageName]['pretty_version'])) {
+ $ranges[] = $installed['versions'][$packageName]['pretty_version'];
+ }
+ if (array_key_exists('aliases', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
+ }
+ if (array_key_exists('replaced', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
+ }
+ if (array_key_exists('provided', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
+ }
+ return implode(' || ', $ranges);
+ }
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+ */
+ public static function getVersion($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
-public static function isInstalled($packageName)
-{
-return isset(self::$installed['versions'][$packageName]);
-}
+ if (!isset($installed['versions'][$packageName]['version'])) {
+ return null;
+ }
+ return $installed['versions'][$packageName]['version'];
+ }
-
-
-
-
-
-
-
-
-
-
-
-
-public static function satisfies(VersionParser $parser, $packageName, $constraint)
-{
-$constraint = $parser->parseConstraints($constraint);
-$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
-
-return $provided->matches($constraint);
-}
-
-
-
-
-
-
-
-
-
-
-public static function getVersionRanges($packageName)
-{
-if (!isset(self::$installed['versions'][$packageName])) {
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-$ranges = array();
-if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {
-$ranges[] = self::$installed['versions'][$packageName]['pretty_version'];
-}
-if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {
-$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);
-}
-if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {
-$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);
-}
-if (array_key_exists('provided', self::$installed['versions'][$packageName])) {
-$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);
-}
-
-return implode(' || ', $ranges);
-}
-
-
-
-
-
-public static function getVersion($packageName)
-{
-if (!isset(self::$installed['versions'][$packageName])) {
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-if (!isset(self::$installed['versions'][$packageName]['version'])) {
-return null;
-}
-
-return self::$installed['versions'][$packageName]['version'];
-}
-
-
-
-
-
-public static function getPrettyVersion($packageName)
-{
-if (!isset(self::$installed['versions'][$packageName])) {
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {
-return null;
-}
-
-return self::$installed['versions'][$packageName]['pretty_version'];
-}
-
-
-
-
-
-public static function getReference($packageName)
-{
-if (!isset(self::$installed['versions'][$packageName])) {
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-if (!isset(self::$installed['versions'][$packageName]['reference'])) {
-return null;
-}
-
-return self::$installed['versions'][$packageName]['reference'];
-}
-
-
-
-
-
-public static function getRootPackage()
-{
-return self::$installed['root'];
-}
-
-
-
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+ */
+ public static function getPrettyVersion($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+ if (!isset($installed['versions'][$packageName]['pretty_version'])) {
+ return null;
+ }
+ return $installed['versions'][$packageName]['pretty_version'];
+ }
-public static function getRawData()
-{
-return self::$installed;
-}
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
+ */
+ public static function getReference($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+ if (!isset($installed['versions'][$packageName]['reference'])) {
+ return null;
+ }
+ return $installed['versions'][$packageName]['reference'];
+ }
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
+ */
+ public static function getInstallPath($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+ return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
+ }
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+ /**
+ * @return array
+ * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}
+ */
+ public static function getRootPackage()
+ {
+ $installed = self::getInstalled();
+ return $installed[0]['root'];
+ }
+ /**
+ * Returns the raw installed.php data for custom implementations
+ *
+ * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
+ * @return array[]
+ * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}
+ */
+ public static function getRawData()
+ {
+ @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+ if (null === self::$installed) {
+ // only require the installed.php file if this file is loaded from its dumped location,
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+ if (substr(__DIR__, -8, 1) !== 'C') {
+ self::$installed = include __DIR__ . '/installed.php';
+ } else {
+ self::$installed = array();
+ }
+ }
+ return self::$installed;
+ }
+ /**
+ * Returns the raw data of all installed.php which are currently loaded for custom implementations
+ *
+ * @return array[]
+ * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
+ */
+ public static function getAllRawData()
+ {
+ return self::getInstalled();
+ }
+ /**
+ * Lets you reload the static array from another file
+ *
+ * This is only useful for complex integrations in which a project needs to use
+ * this class but then also needs to execute another project's autoloader in process,
+ * and wants to ensure both projects have access to their version of installed.php.
+ *
+ * A typical case would be PHPUnit, where it would need to make sure it reads all
+ * the data it needs from this class, then call reload() with
+ * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
+ * the project in which it runs can then also use this class safely, without
+ * interference between PHPUnit's dependencies and the project's dependencies.
+ *
+ * @param array[] $data A vendor/composer/installed.php data set
+ * @return void
+ *
+ * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>} $data
+ */
+ public static function reload($data)
+ {
+ self::$installed = $data;
+ self::$installedByVendor = array();
+ }
+ /**
+ * @return array[]
+ * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
+ */
+ private static function getInstalled()
+ {
+ if (null === self::$canGetVendors) {
+ self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
+ }
+ $installed = array();
+ if (self::$canGetVendors) {
+ foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+ if (isset(self::$installedByVendor[$vendorDir])) {
+ $installed[] = self::$installedByVendor[$vendorDir];
+ } elseif (is_file($vendorDir.'/composer/installed.php')) {
+ $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
+ if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
+ self::$installed = $installed[count($installed) - 1];
+ }
+ }
+ }
+ }
+ if (null === self::$installed) {
+ // only require the installed.php file if this file is loaded from its dumped location,
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+ if (substr(__DIR__, -8, 1) !== 'C') {
+ self::$installed = require __DIR__ . '/installed.php';
+ } else {
+ self::$installed = array();
+ }
+ }
+ $installed[] = self::$installed;
-public static function reload($data)
-{
-self::$installed = $data;
-}
+ return $installed;
+ }
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_classmap.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_classmap.php
index 827360c..1de2dba 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_classmap.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_classmap.php
@@ -6,7 +6,11 @@
$baseDir = dirname($vendorDir);
return array(
+ 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
+ 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
+ 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
+ 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'u2flib_server\\Error' => $vendorDir . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
'u2flib_server\\RegisterRequest' => $vendorDir . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
'u2flib_server\\Registration' => $vendorDir . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_files.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_files.php
index f2c5f70..fac18c7 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_files.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_files.php
@@ -6,5 +6,12 @@
$baseDir = dirname($vendorDir);
return array(
+ 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
+ '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
+ '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
+ 'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
+ '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
+ 'fe62ba7e10580d903cc46d808b5961a4' => $vendorDir . '/tightenco/collect/src/Collect/Support/helpers.php',
+ 'caf31cc6ec7cf2241cb6f12c226c3846' => $vendorDir . '/tightenco/collect/src/Collect/Support/alias.php',
'04c6c5c2f7095ccf6c481d3e53e1776f' => $vendorDir . '/mustangostang/spyc/Spyc.php',
);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_psr4.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_psr4.php
index b1b7514..7c9542e 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_psr4.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_psr4.php
@@ -6,11 +6,23 @@
$baseDir = dirname($vendorDir);
return array(
+ 'Tightenco\\Collect\\' => array($vendorDir . '/tightenco/collect/src/Collect'),
+ 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
+ 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
+ 'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
+ 'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
+ 'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
'RobThree\\Auth\\' => array($vendorDir . '/robthree/twofactorauth/lib'),
+ 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
+ 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
+ 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'PhpMimeMailParser\\' => array($vendorDir . '/php-mime-mail-parser/php-mime-mail-parser/src'),
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
'MatthiasMullie\\PathConverter\\' => array($vendorDir . '/matthiasmullie/path-converter/src'),
'MatthiasMullie\\Minify\\' => array($vendorDir . '/matthiasmullie/minify/src'),
+ 'LdapRecord\\' => array($vendorDir . '/directorytree/ldaprecord/src'),
+ 'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
'Html2Text\\' => array($vendorDir . '/soundasleep/html2text/src'),
'Ddeboer\\Imap\\' => array($vendorDir . '/ddeboer/imap/src'),
+ 'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_real.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_real.php
index d380e48..8a7686a 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_real.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_real.php
@@ -25,7 +25,7 @@
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit873464e4bd965a3168f133248b1b218b', 'loadClassLoader'), true, true);
- self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit873464e4bd965a3168f133248b1b218b', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_static.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_static.php
index 94db388..4d3a5d4 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_static.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/autoload_static.php
@@ -7,16 +7,38 @@
class ComposerStaticInit873464e4bd965a3168f133248b1b218b
{
public static $files = array (
+ 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
+ '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
+ '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
+ 'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
+ '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
+ 'fe62ba7e10580d903cc46d808b5961a4' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/helpers.php',
+ 'caf31cc6ec7cf2241cb6f12c226c3846' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/alias.php',
'04c6c5c2f7095ccf6c481d3e53e1776f' => __DIR__ . '/..' . '/mustangostang/spyc/Spyc.php',
);
public static $prefixLengthsPsr4 = array (
+ 'T' =>
+ array (
+ 'Tightenco\\Collect\\' => 18,
+ ),
+ 'S' =>
+ array (
+ 'Symfony\\Polyfill\\Php80\\' => 23,
+ 'Symfony\\Polyfill\\Mbstring\\' => 26,
+ 'Symfony\\Contracts\\Translation\\' => 30,
+ 'Symfony\\Component\\VarDumper\\' => 28,
+ 'Symfony\\Component\\Translation\\' => 30,
+ ),
'R' =>
array (
'RobThree\\Auth\\' => 14,
),
'P' =>
array (
+ 'Psr\\SimpleCache\\' => 16,
+ 'Psr\\Log\\' => 8,
+ 'Psr\\Container\\' => 14,
'PhpMimeMailParser\\' => 18,
'PHPMailer\\PHPMailer\\' => 20,
),
@@ -25,6 +47,14 @@
'MatthiasMullie\\PathConverter\\' => 29,
'MatthiasMullie\\Minify\\' => 22,
),
+ 'L' =>
+ array (
+ 'LdapRecord\\' => 11,
+ ),
+ 'I' =>
+ array (
+ 'Illuminate\\Contracts\\' => 21,
+ ),
'H' =>
array (
'Html2Text\\' => 10,
@@ -33,13 +63,53 @@
array (
'Ddeboer\\Imap\\' => 13,
),
+ 'C' =>
+ array (
+ 'Carbon\\' => 7,
+ ),
);
public static $prefixDirsPsr4 = array (
+ 'Tightenco\\Collect\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/tightenco/collect/src/Collect',
+ ),
+ 'Symfony\\Polyfill\\Php80\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
+ ),
+ 'Symfony\\Polyfill\\Mbstring\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
+ ),
+ 'Symfony\\Contracts\\Translation\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/translation-contracts',
+ ),
+ 'Symfony\\Component\\VarDumper\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/var-dumper',
+ ),
+ 'Symfony\\Component\\Translation\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/translation',
+ ),
'RobThree\\Auth\\' =>
array (
0 => __DIR__ . '/..' . '/robthree/twofactorauth/lib',
),
+ 'Psr\\SimpleCache\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/simple-cache/src',
+ ),
+ 'Psr\\Log\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
+ ),
+ 'Psr\\Container\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/container/src',
+ ),
'PhpMimeMailParser\\' =>
array (
0 => __DIR__ . '/..' . '/php-mime-mail-parser/php-mime-mail-parser/src',
@@ -56,6 +126,14 @@
array (
0 => __DIR__ . '/..' . '/matthiasmullie/minify/src',
),
+ 'LdapRecord\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/directorytree/ldaprecord/src',
+ ),
+ 'Illuminate\\Contracts\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/illuminate/contracts',
+ ),
'Html2Text\\' =>
array (
0 => __DIR__ . '/..' . '/soundasleep/html2text/src',
@@ -64,6 +142,10 @@
array (
0 => __DIR__ . '/..' . '/ddeboer/imap/src',
),
+ 'Carbon\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon',
+ ),
);
public static $prefixesPsr0 = array (
@@ -77,7 +159,11 @@
);
public static $classMap = array (
+ 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
+ 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
+ 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
+ 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'u2flib_server\\Error' => __DIR__ . '/..' . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
'u2flib_server\\RegisterRequest' => __DIR__ . '/..' . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
'u2flib_server\\Registration' => __DIR__ . '/..' . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/installed.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/installed.json
index 72d1d8d..1ff198c 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/installed.json
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/installed.json
@@ -63,34 +63,34 @@
},
{
"name": "ddeboer/imap",
- "version": "1.11.0",
- "version_normalized": "1.11.0.0",
+ "version": "1.12.1",
+ "version_normalized": "1.12.1.0",
"source": {
"type": "git",
"url": "https://github.com/ddeboer/imap.git",
- "reference": "a089dfcb9d177f921eb5dadc8d4144a44dff22ee"
+ "reference": "dbed05ca67b93509345a820b2859de10c48948fb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ddeboer/imap/zipball/a089dfcb9d177f921eb5dadc8d4144a44dff22ee",
- "reference": "a089dfcb9d177f921eb5dadc8d4144a44dff22ee",
+ "url": "https://api.github.com/repos/ddeboer/imap/zipball/dbed05ca67b93509345a820b2859de10c48948fb",
+ "reference": "dbed05ca67b93509345a820b2859de10c48948fb",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"ext-imap": "*",
"ext-mbstring": "*",
- "php": "^7.3 || ^8.0"
+ "php": "^7.4 || ^8.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^2.16.7",
- "laminas/laminas-mail": "^2.12.3",
- "phpstan/phpstan": "^0.12.57",
- "phpstan/phpstan-phpunit": "^0.12.16",
- "phpstan/phpstan-strict-rules": "^0.12.5",
- "phpunit/phpunit": "^9.4.3"
+ "friendsofphp/php-cs-fixer": "^2.18.6",
+ "laminas/laminas-mail": "^2.14.0",
+ "phpstan/phpstan": "^0.12.84",
+ "phpstan/phpstan-phpunit": "^0.12.18",
+ "phpstan/phpstan-strict-rules": "^0.12.9",
+ "phpunit/phpunit": "^9.5.4"
},
- "time": "2020-11-30T14:52:49+00:00",
+ "time": "2021-04-27T08:38:46+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -124,7 +124,7 @@
],
"support": {
"issues": "https://github.com/ddeboer/imap/issues",
- "source": "https://github.com/ddeboer/imap/tree/1.11.0"
+ "source": "https://github.com/ddeboer/imap/tree/1.12.1"
},
"funding": [
{
@@ -139,18 +139,145 @@
"install-path": "../ddeboer/imap"
},
{
- "name": "matthiasmullie/minify",
- "version": "1.3.65",
- "version_normalized": "1.3.65.0",
+ "name": "directorytree/ldaprecord",
+ "version": "v2.6.3",
+ "version_normalized": "2.6.3.0",
"source": {
"type": "git",
- "url": "https://github.com/matthiasmullie/minify.git",
- "reference": "227f19062451c55a797e0cc667ef983834e6580c"
+ "url": "https://github.com/DirectoryTree/LdapRecord.git",
+ "reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/227f19062451c55a797e0cc667ef983834e6580c",
- "reference": "227f19062451c55a797e0cc667ef983834e6580c",
+ "url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
+ "reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-ldap": "*",
+ "illuminate/contracts": "^5.0|^6.0|^7.0|^8.0",
+ "nesbot/carbon": "^1.0|^2.0",
+ "php": ">=7.3",
+ "psr/log": "^1.0",
+ "psr/simple-cache": "^1.0",
+ "tightenco/collect": "^5.6|^6.0|^7.0|^8.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.0",
+ "phpunit/phpunit": "^8.0",
+ "spatie/ray": "^1.24"
+ },
+ "time": "2021-08-05T21:52:43+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "LdapRecord\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Steve Bauman",
+ "email": "steven_bauman@outlook.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "A fully-featured LDAP ORM.",
+ "homepage": "https://www.ldaprecord.com",
+ "keywords": [
+ "active directory",
+ "ad",
+ "adLDAP",
+ "adldap2",
+ "directory",
+ "ldap",
+ "ldaprecord",
+ "orm",
+ "windows"
+ ],
+ "support": {
+ "docs": "https://ldaprecord.com",
+ "email": "steven_bauman@outlook.com",
+ "issues": "https://github.com/DirectoryTree/LdapRecord/issues",
+ "source": "https://github.com/DirectoryTree/LdapRecord"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/stevebauman",
+ "type": "github"
+ }
+ ],
+ "install-path": "../directorytree/ldaprecord"
+ },
+ {
+ "name": "illuminate/contracts",
+ "version": "v8.53.1",
+ "version_normalized": "8.53.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/illuminate/contracts.git",
+ "reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/illuminate/contracts/zipball/504a34286a1b4c5421c43087d6bd4e176138f6fb",
+ "reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.3|^8.0",
+ "psr/container": "^1.0",
+ "psr/simple-cache": "^1.0"
+ },
+ "time": "2021-08-03T14:03:47+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "8.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Illuminate\\Contracts\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ }
+ ],
+ "description": "The Illuminate Contracts package.",
+ "homepage": "https://laravel.com",
+ "support": {
+ "issues": "https://github.com/laravel/framework/issues",
+ "source": "https://github.com/laravel/framework"
+ },
+ "install-path": "../illuminate/contracts"
+ },
+ {
+ "name": "matthiasmullie/minify",
+ "version": "1.3.66",
+ "version_normalized": "1.3.66.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/matthiasmullie/minify.git",
+ "reference": "45fd3b0f1dfa2c965857c6d4a470bea52adc31a6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/45fd3b0f1dfa2c965857c6d4a470bea52adc31a6",
+ "reference": "45fd3b0f1dfa2c965857c6d4a470bea52adc31a6",
"shasum": ""
},
"require": {
@@ -160,13 +287,13 @@
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2.0",
- "matthiasmullie/scrapbook": "~1.0",
- "phpunit/phpunit": "~4.8"
+ "matthiasmullie/scrapbook": "dev-master",
+ "phpunit/phpunit": ">=4.8"
},
"suggest": {
"psr/cache-implementation": "Cache implementation to use with Minify::cache"
},
- "time": "2020-12-27T21:43:29+00:00",
+ "time": "2021-01-06T15:18:10+00:00",
"bin": [
"bin/minifycss",
"bin/minifyjs"
@@ -201,7 +328,7 @@
],
"support": {
"issues": "https://github.com/matthiasmullie/minify/issues",
- "source": "https://github.com/matthiasmullie/minify/tree/1.3.65"
+ "source": "https://github.com/matthiasmullie/minify/tree/1.3.66"
},
"funding": [
{
@@ -325,6 +452,103 @@
"install-path": "../mustangostang/spyc"
},
{
+ "name": "nesbot/carbon",
+ "version": "2.51.1",
+ "version_normalized": "2.51.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/briannesbitt/Carbon.git",
+ "reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
+ "reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": "^7.1.8 || ^8.0",
+ "symfony/polyfill-mbstring": "^1.0",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/translation": "^3.4 || ^4.0 || ^5.0"
+ },
+ "require-dev": {
+ "doctrine/orm": "^2.7",
+ "friendsofphp/php-cs-fixer": "^2.14 || ^3.0",
+ "kylekatarnls/multi-tester": "^2.0",
+ "phpmd/phpmd": "^2.9",
+ "phpstan/extension-installer": "^1.0",
+ "phpstan/phpstan": "^0.12.54",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.14",
+ "squizlabs/php_codesniffer": "^3.4"
+ },
+ "time": "2021-07-28T13:16:28+00:00",
+ "bin": [
+ "bin/carbon"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-3.x": "3.x-dev",
+ "dev-master": "2.x-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Carbon\\Laravel\\ServiceProvider"
+ ]
+ },
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Carbon\\": "src/Carbon/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Brian Nesbitt",
+ "email": "brian@nesbot.com",
+ "homepage": "https://markido.com"
+ },
+ {
+ "name": "kylekatarnls",
+ "homepage": "https://github.com/kylekatarnls"
+ }
+ ],
+ "description": "An API extension for DateTime that supports 281 different languages.",
+ "homepage": "https://carbon.nesbot.com",
+ "keywords": [
+ "date",
+ "datetime",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/briannesbitt/Carbon/issues",
+ "source": "https://github.com/briannesbitt/Carbon"
+ },
+ "funding": [
+ {
+ "url": "https://opencollective.com/Carbon",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../nesbot/carbon"
+ },
+ {
"name": "paragonie/random_compat",
"version": "v9.99.100",
"version_normalized": "9.99.100.0",
@@ -379,34 +603,33 @@
},
{
"name": "php-mime-mail-parser/php-mime-mail-parser",
- "version": "5.0.5",
- "version_normalized": "5.0.5.0",
+ "version": "7.0.0",
+ "version_normalized": "7.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-mime-mail-parser/php-mime-mail-parser.git",
- "reference": "27983433aabeccee832573c3c56e6a4855e57745"
+ "reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/27983433aabeccee832573c3c56e6a4855e57745",
- "reference": "27983433aabeccee832573c3c56e6a4855e57745",
+ "url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/9d09a017f3f103fec8456211a4a538b80e0eca0d",
+ "reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d",
"shasum": ""
},
"require": {
"ext-mailparse": "*",
- "php": "^7.1"
+ "php": "^7.2|^8.0"
},
"replace": {
"exorus/php-mime-mail-parser": "*",
"messaged/php-mime-mail-parser": "*"
},
"require-dev": {
- "php-coveralls/php-coveralls": "^2.1",
- "phpunit/php-token-stream": "^3.0",
- "phpunit/phpunit": "^7.0",
- "squizlabs/php_codesniffer": "^3.4"
+ "php-coveralls/php-coveralls": "^2.2",
+ "phpunit/phpunit": "^8.0",
+ "squizlabs/php_codesniffer": "^3.5"
},
- "time": "2019-09-23T11:57:58+00:00",
+ "time": "2021-02-25T17:21:57+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -450,7 +673,7 @@
"role": "Developer"
}
],
- "description": "A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).",
+ "description": "A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).",
"homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
"keywords": [
"MimeMailParser",
@@ -460,21 +683,31 @@
"parser",
"php"
],
+ "support": {
+ "issues": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/issues",
+ "source": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/tree/7.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/eXorus",
+ "type": "github"
+ }
+ ],
"install-path": "../php-mime-mail-parser/php-mime-mail-parser"
},
{
"name": "phpmailer/phpmailer",
- "version": "v6.2.0",
- "version_normalized": "6.2.0.0",
+ "version": "v6.5.0",
+ "version_normalized": "6.5.0.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
- "reference": "e38888a75c070304ca5514197d4847a59a5c853f"
+ "reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e38888a75c070304ca5514197d4847a59a5c853f",
- "reference": "e38888a75c070304ca5514197d4847a59a5c853f",
+ "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a5b5c43e50b7fba655f793ad27303cd74c57363c",
+ "reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c",
"shasum": ""
},
"require": {
@@ -492,14 +725,14 @@
"yoast/phpunit-polyfills": "^0.2.0"
},
"suggest": {
- "ext-mbstring": "Needed to send email in multibyte encoding charset",
+ "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
"psr/log": "For optional PSR-3 debug logging",
"stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
},
- "time": "2020-11-25T15:24:57+00:00",
+ "time": "2021-06-16T14:33:43+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -531,7 +764,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
- "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.2.0"
+ "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.5.0"
},
"funding": [
{
@@ -542,27 +775,190 @@
"install-path": "../phpmailer/phpmailer"
},
{
- "name": "robthree/twofactorauth",
- "version": "1.7.0",
- "version_normalized": "1.7.0.0",
+ "name": "psr/container",
+ "version": "1.1.1",
+ "version_normalized": "1.1.1.0",
"source": {
"type": "git",
- "url": "https://github.com/RobThree/TwoFactorAuth.git",
- "reference": "37983bf675c5baca09d19d6705170489d0df0002"
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/37983bf675c5baca09d19d6705170489d0df0002",
- "reference": "37983bf675c5baca09d19d6705170489d0df0002",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
+ "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "time": "2021-03-05T17:36:06+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/1.1.1"
+ },
+ "install-path": "../psr/container"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.1.4",
+ "version_normalized": "1.1.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2021-05-03T11:20:27+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/1.1.4"
+ },
+ "install-path": "../psr/log"
+ },
+ {
+ "name": "psr/simple-cache",
+ "version": "1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2017-10-23T01:57:42+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for simple caching",
+ "keywords": [
+ "cache",
+ "caching",
+ "psr",
+ "psr-16",
+ "simple-cache"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/simple-cache/tree/master"
+ },
+ "install-path": "../psr/simple-cache"
+ },
+ {
+ "name": "robthree/twofactorauth",
+ "version": "1.8.0",
+ "version_normalized": "1.8.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/RobThree/TwoFactorAuth.git",
+ "reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/30a38627ae1e7c9399dae67e265063cd6ec5276c",
+ "reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c",
"shasum": ""
},
"require": {
"php": ">=5.6.0"
},
"require-dev": {
+ "php-parallel-lint/php-parallel-lint": "^1.2",
"phpunit/phpunit": "@stable"
},
- "time": "2020-01-02T19:56:46+00:00",
+ "suggest": {
+ "bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider",
+ "endroid/qr-code": "Needed for EndroidQrCodeProvider"
+ },
+ "time": "2021-03-09T18:24:05+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -593,6 +989,20 @@
"php",
"tfa"
],
+ "support": {
+ "issues": "https://github.com/RobThree/TwoFactorAuth/issues",
+ "source": "https://github.com/RobThree/TwoFactorAuth"
+ },
+ "funding": [
+ {
+ "url": "https://paypal.me/robiii",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/RobThree",
+ "type": "github"
+ }
+ ],
"install-path": "../robthree/twofactorauth"
},
{
@@ -649,6 +1059,572 @@
"install-path": "../soundasleep/html2text"
},
{
+ "name": "symfony/deprecation-contracts",
+ "version": "v2.4.0",
+ "version_normalized": "2.4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
+ "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "time": "2021-03-23T23:28:01+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/deprecation-contracts"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.23.1",
+ "version_normalized": "1.23.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
+ "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "time": "2021-05-27T12:26:48+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.23-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/polyfill-mbstring"
+ },
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.23.1",
+ "version_normalized": "1.23.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
+ "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "time": "2021-07-28T13:41:28+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.23-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ],
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/polyfill-php80"
+ },
+ {
+ "name": "symfony/translation",
+ "version": "v5.3.4",
+ "version_normalized": "5.3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation.git",
+ "reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
+ "reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/translation-contracts": "^2.3"
+ },
+ "conflict": {
+ "symfony/config": "<4.4",
+ "symfony/dependency-injection": "<5.0",
+ "symfony/http-kernel": "<5.0",
+ "symfony/twig-bundle": "<5.0",
+ "symfony/yaml": "<4.4"
+ },
+ "provide": {
+ "symfony/translation-implementation": "2.3"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^4.4|^5.0",
+ "symfony/console": "^4.4|^5.0",
+ "symfony/dependency-injection": "^5.0",
+ "symfony/finder": "^4.4|^5.0",
+ "symfony/http-kernel": "^5.0",
+ "symfony/intl": "^4.4|^5.0",
+ "symfony/polyfill-intl-icu": "^1.21",
+ "symfony/service-contracts": "^1.1.2|^2",
+ "symfony/yaml": "^4.4|^5.0"
+ },
+ "suggest": {
+ "psr/log-implementation": "To use logging capability in translator",
+ "symfony/config": "",
+ "symfony/yaml": ""
+ },
+ "time": "2021-07-25T09:39:16+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\Translation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides tools to internationalize your application",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/translation/tree/v5.3.4"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/translation"
+ },
+ {
+ "name": "symfony/translation-contracts",
+ "version": "v2.4.0",
+ "version_normalized": "2.4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation-contracts.git",
+ "reference": "95c812666f3e91db75385749fe219c5e494c7f95"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95",
+ "reference": "95c812666f3e91db75385749fe219c5e494c7f95",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5"
+ },
+ "suggest": {
+ "symfony/translation-implementation": ""
+ },
+ "time": "2021-03-23T23:28:01+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Translation\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to translation",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/translation-contracts/tree/v2.4.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/translation-contracts"
+ },
+ {
+ "name": "symfony/var-dumper",
+ "version": "v5.3.6",
+ "version_normalized": "5.3.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-dumper.git",
+ "reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
+ "reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<5.4.3",
+ "symfony/console": "<4.4"
+ },
+ "require-dev": {
+ "ext-iconv": "*",
+ "symfony/console": "^4.4|^5.0",
+ "symfony/process": "^4.4|^5.0",
+ "twig/twig": "^2.13|^3.0.4"
+ },
+ "suggest": {
+ "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
+ "ext-intl": "To show region name in time zone dump",
+ "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
+ },
+ "time": "2021-07-27T01:56:02+00:00",
+ "bin": [
+ "Resources/bin/var-dump-server"
+ ],
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "Resources/functions/dump.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\VarDumper\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides mechanisms for walking through any arbitrary PHP variable",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "debug",
+ "dump"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/var-dumper/tree/v5.3.6"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/var-dumper"
+ },
+ {
+ "name": "tightenco/collect",
+ "version": "v8.34.0",
+ "version_normalized": "8.34.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/tighten/collect.git",
+ "reference": "b069783ab0c547bb894ebcf8e7f6024bb401f9d2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/tighten/collect/zipball/b069783ab0c547bb894ebcf8e7f6024bb401f9d2",
+ "reference": "b069783ab0c547bb894ebcf8e7f6024bb401f9d2",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2|^8.0",
+ "symfony/var-dumper": "^3.4 || ^4.0 || ^5.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.0",
+ "nesbot/carbon": "^2.23.0",
+ "phpunit/phpunit": "^8.3"
+ },
+ "time": "2021-03-29T21:29:00+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "src/Collect/Support/helpers.php",
+ "src/Collect/Support/alias.php"
+ ],
+ "psr-4": {
+ "Tightenco\\Collect\\": "src/Collect"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylorotwell@gmail.com"
+ }
+ ],
+ "description": "Collect - Illuminate Collections as a separate package.",
+ "keywords": [
+ "collection",
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/tighten/collect/issues",
+ "source": "https://github.com/tighten/collect/tree/v8.34.0"
+ },
+ "install-path": "../tightenco/collect"
+ },
+ {
"name": "yubico/u2flib-server",
"version": "1.0.2",
"version_normalized": "1.0.2.0",
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/installed.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/installed.php
index 189c9b7..2e6adce 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/installed.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/installed.php
@@ -1,137 +1,257 @@
-<?php return array (
- 'root' =>
- array (
- 'pretty_version' => '1.0.0+no-version-set',
- 'version' => '1.0.0.0',
- 'aliases' =>
- array (
+<?php return array(
+ 'root' => array(
+ 'pretty_version' => '1.0.0+no-version-set',
+ 'version' => '1.0.0.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../../',
+ 'aliases' => array(),
+ 'reference' => NULL,
+ 'name' => '__root__',
+ 'dev' => true,
),
- 'reference' => NULL,
- 'name' => '__root__',
- ),
- 'versions' =>
- array (
- '__root__' =>
- array (
- 'pretty_version' => '1.0.0+no-version-set',
- 'version' => '1.0.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => NULL,
+ 'versions' => array(
+ '__root__' => array(
+ 'pretty_version' => '1.0.0+no-version-set',
+ 'version' => '1.0.0.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../../',
+ 'aliases' => array(),
+ 'reference' => NULL,
+ 'dev_requirement' => false,
+ ),
+ 'bshaffer/oauth2-server-php' => array(
+ 'pretty_version' => 'v1.11.1',
+ 'version' => '1.11.1.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../bshaffer/oauth2-server-php',
+ 'aliases' => array(),
+ 'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
+ 'dev_requirement' => false,
+ ),
+ 'ddeboer/imap' => array(
+ 'pretty_version' => '1.12.1',
+ 'version' => '1.12.1.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../ddeboer/imap',
+ 'aliases' => array(),
+ 'reference' => 'dbed05ca67b93509345a820b2859de10c48948fb',
+ 'dev_requirement' => false,
+ ),
+ 'directorytree/ldaprecord' => array(
+ 'pretty_version' => 'v2.6.3',
+ 'version' => '2.6.3.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../directorytree/ldaprecord',
+ 'aliases' => array(),
+ 'reference' => '5c93ec6d1ef458290825a8b0a148946dce7c1e7a',
+ 'dev_requirement' => false,
+ ),
+ 'exorus/php-mime-mail-parser' => array(
+ 'dev_requirement' => false,
+ 'replaced' => array(
+ 0 => '*',
+ ),
+ ),
+ 'illuminate/contracts' => array(
+ 'pretty_version' => 'v8.53.1',
+ 'version' => '8.53.1.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../illuminate/contracts',
+ 'aliases' => array(),
+ 'reference' => '504a34286a1b4c5421c43087d6bd4e176138f6fb',
+ 'dev_requirement' => false,
+ ),
+ 'matthiasmullie/minify' => array(
+ 'pretty_version' => '1.3.66',
+ 'version' => '1.3.66.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../matthiasmullie/minify',
+ 'aliases' => array(),
+ 'reference' => '45fd3b0f1dfa2c965857c6d4a470bea52adc31a6',
+ 'dev_requirement' => false,
+ ),
+ 'matthiasmullie/path-converter' => array(
+ 'pretty_version' => '1.1.3',
+ 'version' => '1.1.3.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../matthiasmullie/path-converter',
+ 'aliases' => array(),
+ 'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
+ 'dev_requirement' => false,
+ ),
+ 'messaged/php-mime-mail-parser' => array(
+ 'dev_requirement' => false,
+ 'replaced' => array(
+ 0 => '*',
+ ),
+ ),
+ 'mustangostang/spyc' => array(
+ 'pretty_version' => '0.6.3',
+ 'version' => '0.6.3.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../mustangostang/spyc',
+ 'aliases' => array(),
+ 'reference' => '4627c838b16550b666d15aeae1e5289dd5b77da0',
+ 'dev_requirement' => false,
+ ),
+ 'nesbot/carbon' => array(
+ 'pretty_version' => '2.51.1',
+ 'version' => '2.51.1.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nesbot/carbon',
+ 'aliases' => array(),
+ 'reference' => '8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922',
+ 'dev_requirement' => false,
+ ),
+ 'paragonie/random_compat' => array(
+ 'pretty_version' => 'v9.99.100',
+ 'version' => '9.99.100.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../paragonie/random_compat',
+ 'aliases' => array(),
+ 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
+ 'dev_requirement' => false,
+ ),
+ 'php-mime-mail-parser/php-mime-mail-parser' => array(
+ 'pretty_version' => '7.0.0',
+ 'version' => '7.0.0.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../php-mime-mail-parser/php-mime-mail-parser',
+ 'aliases' => array(),
+ 'reference' => '9d09a017f3f103fec8456211a4a538b80e0eca0d',
+ 'dev_requirement' => false,
+ ),
+ 'phpmailer/phpmailer' => array(
+ 'pretty_version' => 'v6.5.0',
+ 'version' => '6.5.0.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../phpmailer/phpmailer',
+ 'aliases' => array(),
+ 'reference' => 'a5b5c43e50b7fba655f793ad27303cd74c57363c',
+ 'dev_requirement' => false,
+ ),
+ 'psr/container' => array(
+ 'pretty_version' => '1.1.1',
+ 'version' => '1.1.1.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../psr/container',
+ 'aliases' => array(),
+ 'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
+ 'dev_requirement' => false,
+ ),
+ 'psr/log' => array(
+ 'pretty_version' => '1.1.4',
+ 'version' => '1.1.4.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../psr/log',
+ 'aliases' => array(),
+ 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
+ 'dev_requirement' => false,
+ ),
+ 'psr/simple-cache' => array(
+ 'pretty_version' => '1.0.1',
+ 'version' => '1.0.1.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../psr/simple-cache',
+ 'aliases' => array(),
+ 'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
+ 'dev_requirement' => false,
+ ),
+ 'robthree/twofactorauth' => array(
+ 'pretty_version' => '1.8.0',
+ 'version' => '1.8.0.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../robthree/twofactorauth',
+ 'aliases' => array(),
+ 'reference' => '30a38627ae1e7c9399dae67e265063cd6ec5276c',
+ 'dev_requirement' => false,
+ ),
+ 'soundasleep/html2text' => array(
+ 'pretty_version' => '0.5.0',
+ 'version' => '0.5.0.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../soundasleep/html2text',
+ 'aliases' => array(),
+ 'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
+ 'dev_requirement' => false,
+ ),
+ 'symfony/deprecation-contracts' => array(
+ 'pretty_version' => 'v2.4.0',
+ 'version' => '2.4.0.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
+ 'aliases' => array(),
+ 'reference' => '5f38c8804a9e97d23e0c8d63341088cd8a22d627',
+ 'dev_requirement' => false,
+ ),
+ 'symfony/polyfill-mbstring' => array(
+ 'pretty_version' => 'v1.23.1',
+ 'version' => '1.23.1.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
+ 'aliases' => array(),
+ 'reference' => '9174a3d80210dca8daa7f31fec659150bbeabfc6',
+ 'dev_requirement' => false,
+ ),
+ 'symfony/polyfill-php80' => array(
+ 'pretty_version' => 'v1.23.1',
+ 'version' => '1.23.1.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../symfony/polyfill-php80',
+ 'aliases' => array(),
+ 'reference' => '1100343ed1a92e3a38f9ae122fc0eb21602547be',
+ 'dev_requirement' => false,
+ ),
+ 'symfony/translation' => array(
+ 'pretty_version' => 'v5.3.4',
+ 'version' => '5.3.4.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../symfony/translation',
+ 'aliases' => array(),
+ 'reference' => 'd89ad7292932c2699cbe4af98d72c5c6bbc504c1',
+ 'dev_requirement' => false,
+ ),
+ 'symfony/translation-contracts' => array(
+ 'pretty_version' => 'v2.4.0',
+ 'version' => '2.4.0.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../symfony/translation-contracts',
+ 'aliases' => array(),
+ 'reference' => '95c812666f3e91db75385749fe219c5e494c7f95',
+ 'dev_requirement' => false,
+ ),
+ 'symfony/translation-implementation' => array(
+ 'dev_requirement' => false,
+ 'provided' => array(
+ 0 => '2.3',
+ ),
+ ),
+ 'symfony/var-dumper' => array(
+ 'pretty_version' => 'v5.3.6',
+ 'version' => '5.3.6.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../symfony/var-dumper',
+ 'aliases' => array(),
+ 'reference' => '3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0',
+ 'dev_requirement' => false,
+ ),
+ 'tightenco/collect' => array(
+ 'pretty_version' => 'v8.34.0',
+ 'version' => '8.34.0.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../tightenco/collect',
+ 'aliases' => array(),
+ 'reference' => 'b069783ab0c547bb894ebcf8e7f6024bb401f9d2',
+ 'dev_requirement' => false,
+ ),
+ 'yubico/u2flib-server' => array(
+ 'pretty_version' => '1.0.2',
+ 'version' => '1.0.2.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../yubico/u2flib-server',
+ 'aliases' => array(),
+ 'reference' => '55d813acf68212ad2cadecde07551600d6971939',
+ 'dev_requirement' => false,
+ ),
),
- 'bshaffer/oauth2-server-php' =>
- array (
- 'pretty_version' => 'v1.11.1',
- 'version' => '1.11.1.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
- ),
- 'ddeboer/imap' =>
- array (
- 'pretty_version' => '1.11.0',
- 'version' => '1.11.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => 'a089dfcb9d177f921eb5dadc8d4144a44dff22ee',
- ),
- 'exorus/php-mime-mail-parser' =>
- array (
- 'replaced' =>
- array (
- 0 => '*',
- ),
- ),
- 'matthiasmullie/minify' =>
- array (
- 'pretty_version' => '1.3.65',
- 'version' => '1.3.65.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '227f19062451c55a797e0cc667ef983834e6580c',
- ),
- 'matthiasmullie/path-converter' =>
- array (
- 'pretty_version' => '1.1.3',
- 'version' => '1.1.3.0',
- 'aliases' =>
- array (
- ),
- 'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
- ),
- 'messaged/php-mime-mail-parser' =>
- array (
- 'replaced' =>
- array (
- 0 => '*',
- ),
- ),
- 'mustangostang/spyc' =>
- array (
- 'pretty_version' => '0.6.3',
- 'version' => '0.6.3.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '4627c838b16550b666d15aeae1e5289dd5b77da0',
- ),
- 'paragonie/random_compat' =>
- array (
- 'pretty_version' => 'v9.99.100',
- 'version' => '9.99.100.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
- ),
- 'php-mime-mail-parser/php-mime-mail-parser' =>
- array (
- 'pretty_version' => '5.0.5',
- 'version' => '5.0.5.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '27983433aabeccee832573c3c56e6a4855e57745',
- ),
- 'phpmailer/phpmailer' =>
- array (
- 'pretty_version' => 'v6.2.0',
- 'version' => '6.2.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => 'e38888a75c070304ca5514197d4847a59a5c853f',
- ),
- 'robthree/twofactorauth' =>
- array (
- 'pretty_version' => '1.7.0',
- 'version' => '1.7.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '37983bf675c5baca09d19d6705170489d0df0002',
- ),
- 'soundasleep/html2text' =>
- array (
- 'pretty_version' => '0.5.0',
- 'version' => '0.5.0.0',
- 'aliases' =>
- array (
- ),
- 'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
- ),
- 'yubico/u2flib-server' =>
- array (
- 'pretty_version' => '1.0.2',
- 'version' => '1.0.2.0',
- 'aliases' =>
- array (
- ),
- 'reference' => '55d813acf68212ad2cadecde07551600d6971939',
- ),
- ),
);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/platform_check.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/platform_check.php
index 92370c5..580fa96 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/platform_check.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/composer/platform_check.php
@@ -4,8 +4,8 @@
$issues = array();
-if (!(PHP_VERSION_ID >= 70300)) {
- $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.';
+if (!(PHP_VERSION_ID >= 70400)) {
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/CHANGELOG.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/CHANGELOG.md
deleted file mode 100644
index 4ddae6e..0000000
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/CHANGELOG.md
+++ /dev/null
@@ -1,678 +0,0 @@
-# Changelog
-
-## [1.11.0](https://github.com/ddeboer/imap/tree/1.11.0) (2020-11-30)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.10.1...1.11.0)
-
-**Implemented enhancements:**
-
-- PHP 8 Compatibility [\#481](https://github.com/ddeboer/imap/issues/481)
-- \[GA\] PHP 8 compatibility fix [\#483](https://github.com/ddeboer/imap/pull/483) ([Slamdunk](https://github.com/Slamdunk))
-- Support PHP 8.0, require PHP 7.3 [\#482](https://github.com/ddeboer/imap/pull/482) ([Slamdunk](https://github.com/Slamdunk))
-
-**Fixed bugs:**
-
-- Fix: Outlook date format [\#480](https://github.com/ddeboer/imap/pull/480) ([gajosadrian](https://github.com/gajosadrian))
-
-**Closed issues:**
-
-- Closing Connection [\#479](https://github.com/ddeboer/imap/issues/479)
-- Problem with charset of message part / DataPartInfo [\#475](https://github.com/ddeboer/imap/issues/475)
-- Unsupported charset "X-UNKNOWN" [\#425](https://github.com/ddeboer/imap/issues/425)
-
-## [1.10.1](https://github.com/ddeboer/imap/tree/1.10.1) (2020-08-26)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.10.0...1.10.1)
-
-**Fixed bugs:**
-
-- getThread and getMessageSequence not using with the same id [\#469](https://github.com/ddeboer/imap/issues/469)
-- imap\_thread: use absolude ids [\#474](https://github.com/ddeboer/imap/pull/474) ([Slamdunk](https://github.com/Slamdunk))
-
-**Closed issues:**
-
-- How to get a message by Message-ID [\#472](https://github.com/ddeboer/imap/issues/472)
-- Mail with e-sign [\#467](https://github.com/ddeboer/imap/issues/467)
-- Duplicate method definition in MessageInterface [\#455](https://github.com/ddeboer/imap/issues/455)
-- Missed errors in search method [\#444](https://github.com/ddeboer/imap/issues/444)
-
-**Merged pull requests:**
-
-- Subtype not always present [\#473](https://github.com/ddeboer/imap/pull/473) ([Piskvor](https://github.com/Piskvor))
-- Improved error handling for message search method [\#445](https://github.com/ddeboer/imap/pull/445) ([ikarol](https://github.com/ikarol))
-
-## [1.10.0](https://github.com/ddeboer/imap/tree/1.10.0) (2020-01-24)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.9.0...1.10.0)
-
-**Implemented enhancements:**
-
-- Handle comments \(CFWS\) in Date header + not-valid formats [\#439](https://github.com/ddeboer/imap/pull/439) ([pupaxxo](https://github.com/pupaxxo))
-- Support PHP 7.4, require PHP 7.2 [\#433](https://github.com/ddeboer/imap/pull/433) ([Slamdunk](https://github.com/Slamdunk))
-
-**Closed issues:**
-
-- Invalid Date header when trying to fetching date on not RFC compliant emails [\#438](https://github.com/ddeboer/imap/issues/438)
-
-**Merged pull requests:**
-
-- Clear the last used mailbox cache when closing a connection [\#447](https://github.com/ddeboer/imap/pull/447) ([dhzavann](https://github.com/dhzavann))
-- README: update PHP version to match composer.json [\#441](https://github.com/ddeboer/imap/pull/441) ([Slamdunk](https://github.com/Slamdunk))
-- Typo [\#440](https://github.com/ddeboer/imap/pull/440) ([OskarStark](https://github.com/OskarStark))
-
-## [1.9.0](https://github.com/ddeboer/imap/tree/1.9.0) (2019-11-25)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.8.0...1.9.0)
-
-**Implemented enhancements:**
-
-- Quota: let's also test the numbers [\#431](https://github.com/ddeboer/imap/pull/431) ([Slamdunk](https://github.com/Slamdunk))
-- Add getQuota method using imap\_get\_quotaroot to Connection class [\#430](https://github.com/ddeboer/imap/pull/430) ([arkadiusjonczek](https://github.com/arkadiusjonczek))
-
-**Closed issues:**
-
-- markAsSeen\(\) not work [\#415](https://github.com/ddeboer/imap/issues/415)
-
-**Merged pull requests:**
-
-- CS Fix: strip redundant php docs [\#428](https://github.com/ddeboer/imap/pull/428) ([Slamdunk](https://github.com/Slamdunk))
-- Fix: Variable name [\#412](https://github.com/ddeboer/imap/pull/412) ([localheinz](https://github.com/localheinz))
-
-## [1.8.0](https://github.com/ddeboer/imap/tree/1.8.0) (2019-04-15)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.2...1.8.0)
-
-**Implemented enhancements:**
-
-- Add phpstan-strict-rules, expose PartiInterface::getDescription\(\) [\#409](https://github.com/ddeboer/imap/pull/409) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.7.2](https://github.com/ddeboer/imap/tree/1.7.2) (2019-04-12)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.1...1.7.2)
-
-**Fixed bugs:**
-
-- Handle message/rfc822 when content-disposition is missing [\#410](https://github.com/ddeboer/imap/pull/410) ([Daredzik](https://github.com/Daredzik))
-
-## [1.7.1](https://github.com/ddeboer/imap/tree/1.7.1) (2019-03-18)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.0...1.7.1)
-
-**Fixed bugs:**
-
-- Encoding problem with 1.7 [\#405](https://github.com/ddeboer/imap/issues/405)
-- imap\_search/imap\_sort: default params must not be passed if unspecified [\#406](https://github.com/ddeboer/imap/pull/406) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.7.0](https://github.com/ddeboer/imap/tree/1.7.0) (2019-03-04)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.6.0...1.7.0)
-
-**Implemented enhancements:**
-
-- Docker and Travis differs in handling new message eols [\#404](https://github.com/ddeboer/imap/pull/404) ([Slamdunk](https://github.com/Slamdunk))
-- Update PHP-CS-Fixer rules [\#403](https://github.com/ddeboer/imap/pull/403) ([Slamdunk](https://github.com/Slamdunk))
-- Add charset for imap\_search or imap\_sort [\#402](https://github.com/ddeboer/imap/pull/402) ([Slamdunk](https://github.com/Slamdunk))
-- PHPStan clean ups [\#400](https://github.com/ddeboer/imap/pull/400) ([Slamdunk](https://github.com/Slamdunk))
-- Adding an undelete\(\) message method [\#386](https://github.com/ddeboer/imap/pull/386) ([C-Duv](https://github.com/C-Duv))
-
-**Closed issues:**
-
-- Convert from GBK \(X-GBK\) to UTF-8 Issue [\#395](https://github.com/ddeboer/imap/issues/395)
-
-**Merged pull requests:**
-
-- Add new ResourceCheckFailureException to handle imap\_check\(\) false [\#399](https://github.com/ddeboer/imap/pull/399) ([pyatnitsev](https://github.com/pyatnitsev))
-- Remove GBK -\> X-GBK Alias and add X-GBK -\> GBK [\#396](https://github.com/ddeboer/imap/pull/396) ([pyatnitsev](https://github.com/pyatnitsev))
-- Add Feature Requests to README.md [\#394](https://github.com/ddeboer/imap/pull/394) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.6.0](https://github.com/ddeboer/imap/tree/1.6.0) (2018-12-04)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.5...1.6.0)
-
-**Implemented enhancements:**
-
-- Require PHP ^7.1 [\#257](https://github.com/ddeboer/imap/issues/257)
-- Require PHP ^7.1 [\#383](https://github.com/ddeboer/imap/pull/383) ([Slamdunk](https://github.com/Slamdunk))
-- Add ability to pass options and retries to imap\_open [\#382](https://github.com/ddeboer/imap/pull/382) ([Slamdunk](https://github.com/Slamdunk))
-- Docker setup for running tests [\#374](https://github.com/ddeboer/imap/pull/374) ([LeadTechVisas](https://github.com/LeadTechVisas))
-- Get messages by UID sequence [\#373](https://github.com/ddeboer/imap/pull/373) ([LeadTechVisas](https://github.com/LeadTechVisas))
-
-**Fixed bugs:**
-
-- Undeliverable mail: attachment parsing error [\#334](https://github.com/ddeboer/imap/issues/334)
-- imap\_getmailboxes returns false; [\#134](https://github.com/ddeboer/imap/issues/134)
-- Fix mailbox name as only numbers [\#381](https://github.com/ddeboer/imap/pull/381) ([Slamdunk](https://github.com/Slamdunk))
-- Gracefully handle possible non-array return value of imap\_getmailboxes [\#372](https://github.com/ddeboer/imap/pull/372) ([Slamdunk](https://github.com/Slamdunk))
-
-**Closed issues:**
-
-- \[AUTHENTICATIONFAILED\] Authentication failed - Too many login failures [\#368](https://github.com/ddeboer/imap/issues/368)
-- last folder in list [\#353](https://github.com/ddeboer/imap/issues/353)
-- Caching IMAP server connections [\#88](https://github.com/ddeboer/imap/issues/88)
-
-## [1.5.5](https://github.com/ddeboer/imap/tree/1.5.5) (2018-08-21)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.4...1.5.5)
-
-**Fixed bugs:**
-
-- Plain text attachments are not identified as Attachment parts [\#341](https://github.com/ddeboer/imap/issues/341)
-- Handle plain/text attachments without Content-Type header [\#367](https://github.com/ddeboer/imap/pull/367) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.5.4](https://github.com/ddeboer/imap/tree/1.5.4) (2018-08-19)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.3...1.5.4)
-
-**Fixed bugs:**
-
-- Very long filename, result of getFilename\(\) = NULL? [\#365](https://github.com/ddeboer/imap/issues/365)
-- Support RFC2231 attachment filenames [\#366](https://github.com/ddeboer/imap/pull/366) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.5.3](https://github.com/ddeboer/imap/tree/1.5.3) (2018-07-20)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.2...1.5.3)
-
-**Fixed bugs:**
-
-- Dates: handle UT timezone [\#361](https://github.com/ddeboer/imap/pull/361) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.5.2](https://github.com/ddeboer/imap/tree/1.5.2) (2018-07-10)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.1...1.5.2)
-
-**Fixed bugs:**
-
-- Fails to load Message Headers [\#358](https://github.com/ddeboer/imap/issues/358)
-- Handle invalid headers [\#359](https://github.com/ddeboer/imap/pull/359) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.5.1](https://github.com/ddeboer/imap/tree/1.5.1) (2018-05-04)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.0...1.5.1)
-
-**Fixed bugs:**
-
-- getContent\(\) method returns wrong content part [\#342](https://github.com/ddeboer/imap/issues/342)
-- Fix handle of attachment messages with attachments [\#343](https://github.com/ddeboer/imap/pull/343) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.5.0](https://github.com/ddeboer/imap/tree/1.5.0) (2018-03-26)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.4.1...1.5.0)
-
-**Implemented enhancements:**
-
-- ImapResource: cache last opened mailbox [\#328](https://github.com/ddeboer/imap/pull/328) ([Slamdunk](https://github.com/Slamdunk))
-
-**Fixed bugs:**
-
-- AbstractPart::isAttachment\(\) handle unknown part type [\#302](https://github.com/ddeboer/imap/pull/302) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.4.1](https://github.com/ddeboer/imap/tree/1.4.1) (2018-03-22)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.4.0...1.4.1)
-
-**Fixed bugs:**
-
-- Return value of Ddeboer\\Imap\\Message\\AbstractPart::getDecodedContent\(\) must be of the type string, boolean returned [\#284](https://github.com/ddeboer/imap/issues/284)
-- base64\_decode may return false in PHP \< 7.1 [\#324](https://github.com/ddeboer/imap/pull/324) ([Slamdunk](https://github.com/Slamdunk))
-
-**Merged pull requests:**
-
-- Add entry in README about Mailbox::addMessage [\#325](https://github.com/ddeboer/imap/pull/325) ([soywod](https://github.com/soywod))
-
-## [1.4.0](https://github.com/ddeboer/imap/tree/1.4.0) (2018-03-19)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.3.1...1.4.0)
-
-**Implemented enhancements:**
-
-- Lazy load Message [\#320](https://github.com/ddeboer/imap/pull/320) ([Slamdunk](https://github.com/Slamdunk))
-
-**Fixed bugs:**
-
-- Invalid argument supplied for foreach\(\) in Parameters.php line 52 [\#317](https://github.com/ddeboer/imap/issues/317)
-- Message "11964" does not exist: imap\_fetchstructure\(\): Bad message number [\#310](https://github.com/ddeboer/imap/issues/310)
-- imap\_mime\_header\_decode may return false [\#322](https://github.com/ddeboer/imap/pull/322) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.3.1](https://github.com/ddeboer/imap/tree/1.3.1) (2018-03-09)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.3.0...1.3.1)
-
-**Implemented enhancements:**
-
-- Allow empty port [\#312](https://github.com/ddeboer/imap/pull/312) ([Slamdunk](https://github.com/Slamdunk))
-
-**Closed issues:**
-
-- getServerString\(\) with no port [\#311](https://github.com/ddeboer/imap/issues/311)
-
-## [1.3.0](https://github.com/ddeboer/imap/tree/1.3.0) (2018-02-28)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.3...1.3.0)
-
-**Implemented enhancements:**
-
-- Implement bulk-move [\#306](https://github.com/ddeboer/imap/pull/306) ([particleflux](https://github.com/particleflux))
-
-**Closed issues:**
-
-- feature: Bulk move [\#305](https://github.com/ddeboer/imap/issues/305)
-
-**Merged pull requests:**
-
-- README.md: add `Unknown search criterion: OR` note [\#304](https://github.com/ddeboer/imap/pull/304) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.2.3](https://github.com/ddeboer/imap/tree/1.2.3) (2018-02-09)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.2...1.2.3)
-
-**Fixed bugs:**
-
-- $part-\>type can be 9 [\#301](https://github.com/ddeboer/imap/issues/301)
-
-**Merged pull requests:**
-
-- README.md: code-coverage has higher priority than Scrutinizer [\#300](https://github.com/ddeboer/imap/pull/300) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.2.2](https://github.com/ddeboer/imap/tree/1.2.2) (2018-02-05)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.1...1.2.2)
-
-**Implemented enhancements:**
-
-- Allow PHPUnit ^7.0 [\#296](https://github.com/ddeboer/imap/pull/296) ([Slamdunk](https://github.com/Slamdunk))
-
-**Fixed bugs:**
-
-- Attachment-\>getFilename return null [\#297](https://github.com/ddeboer/imap/issues/297)
-- Don't handle multiplart as an attachment [\#298](https://github.com/ddeboer/imap/pull/298) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.2.1](https://github.com/ddeboer/imap/tree/1.2.1) (2018-01-29)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.0...1.2.1)
-
-**Implemented enhancements:**
-
-- Introduce strict comparison [\#289](https://github.com/ddeboer/imap/pull/289) ([Slamdunk](https://github.com/Slamdunk))
-
-**Fixed bugs:**
-
-- Invalid Date header found: "Thur, 04 Jan 2018 06:44:23 +0400" [\#293](https://github.com/ddeboer/imap/issues/293)
-- MessageIterator::current\(\) fails when there are no messages [\#288](https://github.com/ddeboer/imap/issues/288)
-- Remove weekday while parsing date header [\#294](https://github.com/ddeboer/imap/pull/294) ([Slamdunk](https://github.com/Slamdunk))
-- MessageIterator: forbid raw calls [\#290](https://github.com/ddeboer/imap/pull/290) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.2.0](https://github.com/ddeboer/imap/tree/1.2.0) (2018-01-15)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.2...1.2.0)
-
-**Implemented enhancements:**
-
-- Make imap\_append\(\) optional arguments reachable [\#280](https://github.com/ddeboer/imap/pull/280) ([Slamdunk](https://github.com/Slamdunk))
-- PHPStan: introduce static analysis [\#276](https://github.com/ddeboer/imap/pull/276) ([Slamdunk](https://github.com/Slamdunk))
-
-**Fixed bugs:**
-
-- getAttachments\(\) problem when mixin inline and attachment [\#281](https://github.com/ddeboer/imap/issues/281)
-- UnexpectedEncodingException: Cannot decode "5" [\#278](https://github.com/ddeboer/imap/issues/278)
-- Handle correctly multiple nested attachments [\#283](https://github.com/ddeboer/imap/pull/283) ([Slamdunk](https://github.com/Slamdunk))
-- Manageable UnexpectedEncodingException [\#282](https://github.com/ddeboer/imap/pull/282) ([Slamdunk](https://github.com/Slamdunk))
-
-**Closed issues:**
-
-- Appending mail with options [\#279](https://github.com/ddeboer/imap/issues/279)
-
-## [1.1.2](https://github.com/ddeboer/imap/tree/1.1.2) (2017-12-12)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.1...1.1.2)
-
-**Fixed bugs:**
-
-- Unsupported charset "134": mb\_convert\_encoding\(\): Illegal character encoding specified [\#270](https://github.com/ddeboer/imap/issues/270)
-- Support Microsoft charset values [\#271](https://github.com/ddeboer/imap/pull/271) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.1.1](https://github.com/ddeboer/imap/tree/1.1.1) (2017-11-10)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.0...1.1.1)
-
-**Implemented enhancements:**
-
-- Transcoder: expand charset aliases list [\#267](https://github.com/ddeboer/imap/pull/267) ([Slamdunk](https://github.com/Slamdunk))
-
-**Fixed bugs:**
-
-- Charset aliases: fix to lowercase search [\#266](https://github.com/ddeboer/imap/pull/266) ([Slamdunk](https://github.com/Slamdunk))
-
-**Merged pull requests:**
-
-- README.md: add timeout note [\#263](https://github.com/ddeboer/imap/pull/263) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.1.0](https://github.com/ddeboer/imap/tree/1.1.0) (2017-11-06)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.8...1.1.0)
-
-**Implemented enhancements:**
-
-- Deprecate MessageInterface::maskAsSeen\(\) in favour of MessageInterface::markAsSeen\(\) [\#255](https://github.com/ddeboer/imap/pull/255) ([Slamdunk](https://github.com/Slamdunk))
-- Lazy load structured Headers [\#250](https://github.com/ddeboer/imap/pull/250) ([Slamdunk](https://github.com/Slamdunk))
-- Implement imap\_thread [\#249](https://github.com/ddeboer/imap/pull/249) ([Slamdunk](https://github.com/Slamdunk))
-- Require ext-iconv [\#248](https://github.com/ddeboer/imap/pull/248) ([Slamdunk](https://github.com/Slamdunk))
-- Message Part: expose $partNumber [\#244](https://github.com/ddeboer/imap/pull/244) ([wujku](https://github.com/wujku))
-- Add Mockability helpers and documentation [\#236](https://github.com/ddeboer/imap/pull/236) ([Slamdunk](https://github.com/Slamdunk))
-- Add missing interface change for \#225 [\#233](https://github.com/ddeboer/imap/pull/233) ([Slamdunk](https://github.com/Slamdunk))
-- Connection: check if the connection is still active with `imap\_ping` [\#232](https://github.com/ddeboer/imap/pull/232) ([wujku](https://github.com/wujku))
-- Message: add `References` and `In-Reply-To` headers shortcuts [\#230](https://github.com/ddeboer/imap/pull/230) ([wujku](https://github.com/wujku))
-- Added bulk set / clear flags functionality for mailbox messages [\#225](https://github.com/ddeboer/imap/pull/225) ([wujku](https://github.com/wujku))
-
-**Merged pull requests:**
-
-- make docs more obvious [\#252](https://github.com/ddeboer/imap/pull/252) ([lgg](https://github.com/lgg))
-- README.md: add Table of Contents with Travis checker [\#234](https://github.com/ddeboer/imap/pull/234) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.0.8](https://github.com/ddeboer/imap/tree/1.0.8) (2017-10-27)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.7...1.0.8)
-
-**Implemented enhancements:**
-
-- Headers: no catchable exception [\#246](https://github.com/ddeboer/imap/issues/246)
-- imap\_thread [\#113](https://github.com/ddeboer/imap/issues/113)
-
-**Fixed bugs:**
-
-- \[TypeError\] Return value of Ddeboer\Imap\Message\AbstractMessage::getId\(\) must be of the type string, null returned [\#253](https://github.com/ddeboer/imap/issues/253)
-- BasicMessageInterface::getId\(\) can be null [\#254](https://github.com/ddeboer/imap/pull/254) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.0.7](https://github.com/ddeboer/imap/tree/1.0.7) (2017-10-16)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.6...1.0.7)
-
-**Fixed bugs:**
-
-- Problem with a IMAP resource stream [\#245](https://github.com/ddeboer/imap/issues/245)
-- IMAP resource must be checked at every call for mailbox context [\#247](https://github.com/ddeboer/imap/pull/247) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.0.6](https://github.com/ddeboer/imap/tree/1.0.6) (2017-10-12)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.5...1.0.6)
-
-**Fixed bugs:**
-
-- \[TypeError\] Return value of AbstractMessage::getFrom\(\) must be an instance of EmailAddress, null returned [\#241](https://github.com/ddeboer/imap/issues/241)
-- Message: Date header can be absent [\#243](https://github.com/ddeboer/imap/pull/243) ([Slamdunk](https://github.com/Slamdunk))
-- Message: From header can be absent [\#242](https://github.com/ddeboer/imap/pull/242) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.0.5](https://github.com/ddeboer/imap/tree/1.0.5) (2017-10-12)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.4...1.0.5)
-
-**Fixed bugs:**
-
-- Use set\_error\_handler with late exception [\#240](https://github.com/ddeboer/imap/pull/240) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.0.4](https://github.com/ddeboer/imap/tree/1.0.4) (2017-10-11)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.3...1.0.4)
-
-**Implemented enhancements:**
-
-- Avoid \(set|restor\)\_error\_handler [\#239](https://github.com/ddeboer/imap/pull/239) ([Slamdunk](https://github.com/Slamdunk))
-
-**Fixed bugs:**
-
-- Current Transcoder class does not support all charsets. [\#237](https://github.com/ddeboer/imap/issues/237)
-- Relay also iconv during decoding [\#238](https://github.com/ddeboer/imap/pull/238) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.0.3](https://github.com/ddeboer/imap/tree/1.0.3) (2017-10-11)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.2...1.0.3)
-
-**Fixed bugs:**
-
-- Attachment::getFilename\(\) may be null on inline-att, widen return type [\#235](https://github.com/ddeboer/imap/pull/235) ([wujku](https://github.com/wujku))
-
-## [1.0.2](https://github.com/ddeboer/imap/tree/1.0.2) (2017-10-06)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.1...1.0.2)
-
-**Fixed bugs:**
-
-- Issue with saving XML attachments [\#228](https://github.com/ddeboer/imap/issues/228)
-- Do not charset-decode attachments [\#231](https://github.com/ddeboer/imap/pull/231) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.0.1](https://github.com/ddeboer/imap/tree/1.0.1) (2017-10-05)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.0...1.0.1)
-
-**Fixed bugs:**
-
-- Error with attachment charset [\#226](https://github.com/ddeboer/imap/issues/226)
-- If charset is not specified defaults to "us-ascii" [\#227](https://github.com/ddeboer/imap/pull/227) ([Slamdunk](https://github.com/Slamdunk))
-
-## [1.0.0](https://github.com/ddeboer/imap/tree/1.0.0) (2017-10-04)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.2...1.0.0)
-
-**Implemented enhancements:**
-
-- Need getAll for headers [\#200](https://github.com/ddeboer/imap/issues/200)
-- Tests: implement @covers to avoid false positive on code-coverage [\#188](https://github.com/ddeboer/imap/issues/188)
-- Remove commented code [\#174](https://github.com/ddeboer/imap/issues/174)
-- Regex in SearchExpressions [\#157](https://github.com/ddeboer/imap/issues/157)
-- How do I get unread messages count? [\#98](https://github.com/ddeboer/imap/issues/98)
-- Add mocking ability through Interfaces [\#221](https://github.com/ddeboer/imap/pull/221) ([Slamdunk](https://github.com/Slamdunk))
-- Wrap imap resource to periodically check its status [\#220](https://github.com/ddeboer/imap/pull/220) ([Slamdunk](https://github.com/Slamdunk))
-- Add more coding-standard rules [\#218](https://github.com/ddeboer/imap/pull/218) ([Slamdunk](https://github.com/Slamdunk))
-- Always keep unseen: remove keepUnseen, add markAsSeen [\#217](https://github.com/ddeboer/imap/pull/217) ([Slamdunk](https://github.com/Slamdunk))
-- Embedded messages: refactor \#106 [\#216](https://github.com/ddeboer/imap/pull/216) ([Slamdunk](https://github.com/Slamdunk))
-- Headers now extends \ArrayIterator [\#215](https://github.com/ddeboer/imap/pull/215) ([Slamdunk](https://github.com/Slamdunk))
-- Implement imap\_mail\_copy [\#214](https://github.com/ddeboer/imap/pull/214) ([Slamdunk](https://github.com/Slamdunk))
-- Imap sort [\#213](https://github.com/ddeboer/imap/pull/213) ([Slamdunk](https://github.com/Slamdunk))
-- Increased code-coverage [\#211](https://github.com/ddeboer/imap/pull/211) ([Slamdunk](https://github.com/Slamdunk))
-- Update to PHPUnit ^6.2 [\#209](https://github.com/ddeboer/imap/pull/209) ([Slamdunk](https://github.com/Slamdunk))
-- Use specific exceptions to ease user catches [\#208](https://github.com/ddeboer/imap/pull/208) ([Slamdunk](https://github.com/Slamdunk))
-- Wrap Exception on invalid Date header [\#205](https://github.com/ddeboer/imap/pull/205) ([Slamdunk](https://github.com/Slamdunk))
-- Add tests for \#144 set flags functionalities [\#203](https://github.com/ddeboer/imap/pull/203) ([Slamdunk](https://github.com/Slamdunk))
-- Add imap\_fetchheader\(\) functionality to get raw headers [\#202](https://github.com/ddeboer/imap/pull/202) ([Slamdunk](https://github.com/Slamdunk))
-- Parse all email type headers [\#199](https://github.com/ddeboer/imap/pull/199) ([Slamdunk](https://github.com/Slamdunk))
-- Test search conditions [\#198](https://github.com/ddeboer/imap/pull/198) ([Slamdunk](https://github.com/Slamdunk))
-- Mailbox: get status [\#192](https://github.com/ddeboer/imap/pull/192) ([Slamdunk](https://github.com/Slamdunk))
-- SearchExpression is a Search\ConditionInterface [\#191](https://github.com/ddeboer/imap/pull/191) ([Slamdunk](https://github.com/Slamdunk))
-- SearchCondition: \_\_toString\(\) -\> toString\(\) [\#187](https://github.com/ddeboer/imap/pull/187) ([Slamdunk](https://github.com/Slamdunk))
-- Retain imap\_getmailboxes\(\) results [\#184](https://github.com/ddeboer/imap/pull/184) ([Slamdunk](https://github.com/Slamdunk))
-- Add type hints and return types [\#183](https://github.com/ddeboer/imap/pull/183) ([Slamdunk](https://github.com/Slamdunk))
-- Exception: increase verbosity with imap\_alerts\(\) and imap\_errors\(\) [\#182](https://github.com/ddeboer/imap/pull/182) ([Slamdunk](https://github.com/Slamdunk))
-- Add coding-standards [\#181](https://github.com/ddeboer/imap/pull/181) ([Slamdunk](https://github.com/Slamdunk))
-- Travis: re-enable code-coverage on scrutinizer [\#177](https://github.com/ddeboer/imap/pull/177) ([Slamdunk](https://github.com/Slamdunk))
-- Add .gitattributes to remove from releases unneded files [\#173](https://github.com/ddeboer/imap/pull/173) ([Slamdunk](https://github.com/Slamdunk))
-- Travis: use local Dovecot installation [\#170](https://github.com/ddeboer/imap/pull/170) ([Slamdunk](https://github.com/Slamdunk))
-- Need all Headers in string format [\#149](https://github.com/ddeboer/imap/pull/149) ([FlashWS](https://github.com/FlashWS))
-- Get raw mail [\#146](https://github.com/ddeboer/imap/pull/146) ([styxit](https://github.com/styxit))
-- add getBcc\(\), Set, Clear Flag\(\Seen, \Answered, \Flagged, \Deleted, and \Draft\), getHeadersRaw\(\) [\#144](https://github.com/ddeboer/imap/pull/144) ([trungpv93](https://github.com/trungpv93))
-
-**Fixed bugs:**
-
-- Search\Condition needs charset escaping/indication [\#190](https://github.com/ddeboer/imap/issues/190)
-- imap\_utf7\_\(encode|decode\) -\> mb\_convert\_encoding [\#185](https://github.com/ddeboer/imap/issues/185)
-- España [\#176](https://github.com/ddeboer/imap/issues/176)
-- getHeaders\(\) decode broke information [\#171](https://github.com/ddeboer/imap/issues/171)
-- Date format for date search condition [\#168](https://github.com/ddeboer/imap/issues/168)
-- Error when trying fetch messages from container [\#167](https://github.com/ddeboer/imap/issues/167)
-- Attachment encoding error [\#158](https://github.com/ddeboer/imap/issues/158)
-- getFilename\(\) is empty and no attachment, even when there is an attachment. [\#142](https://github.com/ddeboer/imap/issues/142)
-- Encoding issues [\#136](https://github.com/ddeboer/imap/issues/136)
-- URGENT: The timezone could not be found in the database [\#135](https://github.com/ddeboer/imap/issues/135)
-- Incorrect transcoding of text attachments [\#132](https://github.com/ddeboer/imap/issues/132)
-- Undefined offset [\#123](https://github.com/ddeboer/imap/issues/123)
-- ICS file not supported as attachment [\#120](https://github.com/ddeboer/imap/issues/120)
-- Should iconv be a requirement? [\#115](https://github.com/ddeboer/imap/issues/115)
-- KeepUnseen doen't work [\#92](https://github.com/ddeboer/imap/issues/92)
-- PHP Fatal error Failed to parse time string in ddeboer/imap/src/Message.php [\#89](https://github.com/ddeboer/imap/issues/89)
-- encoding issue [\#85](https://github.com/ddeboer/imap/issues/85)
-- keepUnseen not working correctly with Hotmail [\#84](https://github.com/ddeboer/imap/issues/84)
-- Iconv Exception [\#78](https://github.com/ddeboer/imap/issues/78)
-- $message-\>getAttachments\(\) doesn't recognize some attachments [\#74](https://github.com/ddeboer/imap/issues/74)
-- Message::move\(\) doesn't work. [\#73](https://github.com/ddeboer/imap/issues/73)
-- Message\Part: part number must distinguish original message [\#223](https://github.com/ddeboer/imap/pull/223) ([Slamdunk](https://github.com/Slamdunk))
-- Recursive Embedded email body bug [\#222](https://github.com/ddeboer/imap/pull/222) ([Slamdunk](https://github.com/Slamdunk))
-- Exclude HTML from allowed attachment subtype [\#212](https://github.com/ddeboer/imap/pull/212) ([Slamdunk](https://github.com/Slamdunk))
-- Fix imap\_mail\_move behaviour and test it [\#207](https://github.com/ddeboer/imap/pull/207) ([Slamdunk](https://github.com/Slamdunk))
-- Undefined encoding: throw exception [\#197](https://github.com/ddeboer/imap/pull/197) ([Slamdunk](https://github.com/Slamdunk))
-- Message charset: mb\_convert\_encoding + aliases [\#196](https://github.com/ddeboer/imap/pull/196) ([Slamdunk](https://github.com/Slamdunk))
-- Mailbox: only UTF-8 names [\#193](https://github.com/ddeboer/imap/pull/193) ([Slamdunk](https://github.com/Slamdunk))
-- Search\Date\AbstractDate: fix format to RFC-3501 [\#189](https://github.com/ddeboer/imap/pull/189) ([Slamdunk](https://github.com/Slamdunk))
-- Travis: fix failing tests [\#172](https://github.com/ddeboer/imap/pull/172) ([Slamdunk](https://github.com/Slamdunk))
-- Return body of single-part HTML message as HTML, not text [\#101](https://github.com/ddeboer/imap/pull/101) ([joker806](https://github.com/joker806))
-- Implement "undisclosed recipients" addresses [\#86](https://github.com/ddeboer/imap/pull/86) ([darit](https://github.com/darit))
-
-**Closed issues:**
-
-- Potential memory issue with attachments [\#195](https://github.com/ddeboer/imap/issues/195)
-- Explain Message::delete [\#175](https://github.com/ddeboer/imap/issues/175)
-- Get raw message [\#161](https://github.com/ddeboer/imap/issues/161)
-- Composer install problem [\#160](https://github.com/ddeboer/imap/issues/160)
-- Transcoder not exist [\#154](https://github.com/ddeboer/imap/issues/154)
-- The library doesn't support using sort by [\#151](https://github.com/ddeboer/imap/issues/151)
-- Office 365 - Array to string conversion error [\#131](https://github.com/ddeboer/imap/issues/131)
-- Is there a method to turn a seen message into an "unseen" one ? [\#130](https://github.com/ddeboer/imap/issues/130)
-- Create mailbox [\#126](https://github.com/ddeboer/imap/issues/126)
-- Move and Delete Message not working [\#112](https://github.com/ddeboer/imap/issues/112)
-- Problem on production server [\#111](https://github.com/ddeboer/imap/issues/111)
-- Authentication failed for a Gmail account [\#109](https://github.com/ddeboer/imap/issues/109)
-- A method to run IMAP commands? [\#83](https://github.com/ddeboer/imap/issues/83)
-
-**Merged pull requests:**
-
-- Update README.md to latest develop changes [\#224](https://github.com/ddeboer/imap/pull/224) ([Slamdunk](https://github.com/Slamdunk))
-- Add Filippo Tessarotto as an author of the package [\#219](https://github.com/ddeboer/imap/pull/219) ([Slamdunk](https://github.com/Slamdunk))
-- README.md: call Connection::expunge after move and delete [\#210](https://github.com/ddeboer/imap/pull/210) ([Slamdunk](https://github.com/Slamdunk))
-- Remove misleading Mailbox::expunge\(\) [\#206](https://github.com/ddeboer/imap/pull/206) ([Slamdunk](https://github.com/Slamdunk))
-- Add CHANGELOG.md [\#194](https://github.com/ddeboer/imap/pull/194) ([Slamdunk](https://github.com/Slamdunk))
-- README.md updates [\#178](https://github.com/ddeboer/imap/pull/178) ([Slamdunk](https://github.com/Slamdunk))
-
-## [0.5.2](https://github.com/ddeboer/imap/tree/0.5.2) (2015-12-03)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.1...0.5.2)
-
-**Closed issues:**
-
-- $message-\>getAttachments\(\) returns null if message has no attachments [\#80](https://github.com/ddeboer/imap/issues/80)
-- Email objects visibility [\#76](https://github.com/ddeboer/imap/issues/76)
-
-**Merged pull requests:**
-
-- Fixed the keepUnseen method [\#95](https://github.com/ddeboer/imap/pull/95) ([aeyoll](https://github.com/aeyoll))
-- Mark Mailbox as countable, fix doc comments [\#91](https://github.com/ddeboer/imap/pull/91) ([krzysiekpiasecki](https://github.com/krzysiekpiasecki))
-- Message::getAttachments confirm to signature [\#82](https://github.com/ddeboer/imap/pull/82) ([boekkooi](https://github.com/boekkooi))
-- Added hasMailbox to Connection [\#81](https://github.com/ddeboer/imap/pull/81) ([boekkooi](https://github.com/boekkooi))
-- Make sure imap connection are reopened [\#79](https://github.com/ddeboer/imap/pull/79) ([joserobleda](https://github.com/joserobleda))
-
-## [0.5.1](https://github.com/ddeboer/imap/tree/0.5.1) (2015-02-01)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.0...0.5.1)
-
-**Closed issues:**
-
-- imap\_open error [\#72](https://github.com/ddeboer/imap/issues/72)
-- $message-\>getAttachments\(\) does not return anything, even though a message has at least one attachment [\#71](https://github.com/ddeboer/imap/issues/71)
-- Prepare docs for 1.0 [\#69](https://github.com/ddeboer/imap/issues/69)
-- "date" header is not reliable [\#63](https://github.com/ddeboer/imap/issues/63)
-- File Attachments don't show up [\#55](https://github.com/ddeboer/imap/issues/55)
-
-**Merged pull requests:**
-
-- Add support for attachments without content disposition [\#70](https://github.com/ddeboer/imap/pull/70) ([ddeboer](https://github.com/ddeboer))
-
-## [0.5.0](https://github.com/ddeboer/imap/tree/0.5.0) (2015-01-24)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/0.4.0...0.5.0)
-
-**Closed issues:**
-
-- Use utf8\_encode\(\) function to encode content [\#66](https://github.com/ddeboer/imap/issues/66)
-- Please add function order by date [\#59](https://github.com/ddeboer/imap/issues/59)
-- mb\_convert\_encoding breaks code [\#57](https://github.com/ddeboer/imap/issues/57)
-- How get I getMessages but newest first ... [\#11](https://github.com/ddeboer/imap/issues/11)
-
-## [0.4.0](https://github.com/ddeboer/imap/tree/0.4.0) (2015-01-04)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/0.3.1...0.4.0)
-
-**Closed issues:**
-
-- Please add 6th parameter to imap\_open call [\#62](https://github.com/ddeboer/imap/issues/62)
-- Should Message::delete\(\) use the Message UID? [\#46](https://github.com/ddeboer/imap/issues/46)
-- mb\_convert\_encoding\(\): Illegal character encoding specified [\#35](https://github.com/ddeboer/imap/issues/35)
-- Deleting a message isn't working [\#30](https://github.com/ddeboer/imap/issues/30)
-- imap\_header doesn't work with message uid [\#26](https://github.com/ddeboer/imap/issues/26)
-
-**Merged pull requests:**
-
-- Added basic requirement [\#61](https://github.com/ddeboer/imap/pull/61) ([nikoskip](https://github.com/nikoskip))
-- FIX: PHP error: "Cannot declare class Ddeboer\Imap\Search\Text\Text ..." [\#58](https://github.com/ddeboer/imap/pull/58) ([racztiborzoltan](https://github.com/racztiborzoltan))
-- Message::delete sets the FT\_UID flag. Fixes \#30 Fixes \#46 [\#54](https://github.com/ddeboer/imap/pull/54) ([ctalbot](https://github.com/ctalbot))
-- Allow binary-encoded part content [\#48](https://github.com/ddeboer/imap/pull/48) ([joker806](https://github.com/joker806))
-- Fix CS [\#47](https://github.com/ddeboer/imap/pull/47) ([xelan](https://github.com/xelan))
-- fixed typo [\#45](https://github.com/ddeboer/imap/pull/45) ([xelan](https://github.com/xelan))
-
-## [0.3.1](https://github.com/ddeboer/imap/tree/0.3.1) (2014-08-11)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/0.3.0...0.3.1)
-
-**Merged pull requests:**
-
-- \imap\_header dosen't work with UID [\#44](https://github.com/ddeboer/imap/pull/44) ([ysramirez](https://github.com/ysramirez))
-
-## [0.3.0](https://github.com/ddeboer/imap/tree/0.3.0) (2014-08-10)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/0.2...0.3.0)
-
-**Closed issues:**
-
-- please remove useless wiki [\#42](https://github.com/ddeboer/imap/issues/42)
-- Travis tests allways fail? [\#40](https://github.com/ddeboer/imap/issues/40)
-- Garbled e-mail body encoding [\#27](https://github.com/ddeboer/imap/issues/27)
-- Improve docs [\#25](https://github.com/ddeboer/imap/issues/25)
-- "undisclosed-recipients" throws error [\#23](https://github.com/ddeboer/imap/issues/23)
-
-**Merged pull requests:**
-
-- correct minor typo [\#43](https://github.com/ddeboer/imap/pull/43) ([cordoval](https://github.com/cordoval))
-- Utf-8 encode body content. [\#39](https://github.com/ddeboer/imap/pull/39) ([cmoralesweb](https://github.com/cmoralesweb))
-- Fix regex parsing the date header \(allowing multiple brackets\) [\#38](https://github.com/ddeboer/imap/pull/38) ([joker806](https://github.com/joker806))
-- Allow empty connection flags [\#34](https://github.com/ddeboer/imap/pull/34) ([joker806](https://github.com/joker806))
-- Fixed typo [\#32](https://github.com/ddeboer/imap/pull/32) ([abhinavkumar940](https://github.com/abhinavkumar940))
-
-## [0.2](https://github.com/ddeboer/imap/tree/0.2) (2013-11-24)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/0.1...0.2)
-
-## [0.1](https://github.com/ddeboer/imap/tree/0.1) (2013-11-22)
-
-[Full Changelog](https://github.com/ddeboer/imap/compare/c02d49cdb9246901bb00d211a0f2aba208f6fab6...0.1)
-
-**Closed issues:**
-
-- Prevent setting SEEN flag [\#20](https://github.com/ddeboer/imap/issues/20)
-- Add tests [\#18](https://github.com/ddeboer/imap/issues/18)
-- delete messages [\#9](https://github.com/ddeboer/imap/issues/9)
-- README is missing basic usage [\#7](https://github.com/ddeboer/imap/issues/7)
-- Subject and other texts are decoded incorrectly [\#3](https://github.com/ddeboer/imap/issues/3)
-
-**Merged pull requests:**
-
-- also fetch inline attachments [\#24](https://github.com/ddeboer/imap/pull/24) ([kaiserlos](https://github.com/kaiserlos))
-- since leading slash is always needed [\#22](https://github.com/ddeboer/imap/pull/22) ([huglester](https://github.com/huglester))
-- Added missed createMailbox\($name\) function [\#19](https://github.com/ddeboer/imap/pull/19) ([burci](https://github.com/burci))
-- Added move and delete function to message + expunge function [\#17](https://github.com/ddeboer/imap/pull/17) ([burci](https://github.com/burci))
-- Clean up some unused variable [\#16](https://github.com/ddeboer/imap/pull/16) ([burci](https://github.com/burci))
-- Fixed mailbox encoding [\#15](https://github.com/ddeboer/imap/pull/15) ([burci](https://github.com/burci))
-- Create new mailbox [\#14](https://github.com/ddeboer/imap/pull/14) ([burci](https://github.com/burci))
-- Fixed bug in getDecodedContent with 'format=flowed' email [\#13](https://github.com/ddeboer/imap/pull/13) ([burci](https://github.com/burci))
-- Fixed date parsing for some imap servers [\#12](https://github.com/ddeboer/imap/pull/12) ([thelfensdrfer](https://github.com/thelfensdrfer))
-- Add support for more complex search expressions. [\#10](https://github.com/ddeboer/imap/pull/10) ([jamesiarmes](https://github.com/jamesiarmes))
-- Allow user to change server connection flags [\#6](https://github.com/ddeboer/imap/pull/6) ([mvar](https://github.com/mvar))
-- Improvements in EmailAddress class [\#4](https://github.com/ddeboer/imap/pull/4) ([mvar](https://github.com/mvar))
-
-
-
-\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/README.md
index 6b16183..c57ab01 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/README.md
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/README.md
@@ -1,37 +1,15 @@
-# IMAP library
+# PHP IMAP library
[![Latest Stable Version](https://img.shields.io/packagist/v/ddeboer/imap.svg)](https://packagist.org/packages/ddeboer/imap)
[![Downloads](https://img.shields.io/packagist/dt/ddeboer/imap.svg)](https://packagist.org/packages/ddeboer/imap)
[![Integrate](https://github.com/ddeboer/imap/workflows/Integrate/badge.svg?branch=master)](https://github.com/ddeboer/imap/actions)
[![Code Coverage](https://codecov.io/gh/ddeboer/imap/coverage.svg?branch=master)](https://codecov.io/gh/ddeboer/imap?branch=master)
-A PHP 7.3+ library to read and process e-mails over IMAP.
+A PHP IMAP library to read and process e-mails over IMAP protocol, built with robust Object-Oriented architecture.
-This library requires [IMAP](https://secure.php.net/manual/en/book.imap.php),
-[iconv](https://secure.php.net/manual/en/book.iconv.php) and
-[Multibyte String](https://secure.php.net/manual/en/book.mbstring.php) extensions installed.
-
-## Table of Contents
-
-1. [Feature Requests](#feature-requests)
-1. [Installation](#installation)
-1. [Usage](#usage)
- 1. [Connect and Authenticate](#connect-and-authenticate)
- 1. [Mailboxes](#mailboxes)
- 1. [Messages](#messages)
- 1. [Searching for Messages](#searching-for-messages)
- 1. [Unknown search criterion: OR](#unknown-search-criterion-or)
- 1. [Message Properties and Operations](#message-properties-and-operations)
- 1. [Message Attachments](#message-attachments)
- 1. [Embedded Messages](#embedded-messages)
- 1. [Timeouts](#timeouts)
-1. [Mock the library](#mock-the-library)
-1. [Running the Tests](#running-the-tests)
- 1. [Running Tests using Docker](#running-tests-using-docker)
-
-## Feature Requests
-
-[![Feature Requests](https://feathub.com/ddeboer/imap?format=svg)](https://feathub.com/ddeboer/imap)
+This library requires PHP >= 7.4 with [IMAP](https://www.php.net/manual/en/book.imap.php),
+[iconv](https://www.php.net/manual/en/book.iconv.php) and
+[Multibyte String](https://www.php.net/manual/en/book.mbstring.php) extensions installed.
## Installation
@@ -236,7 +214,6 @@
```php
$mailbox = $connection->getMailbox('another-mailbox');
$message->move($mailbox);
-$connection->expunge();
```
Deleting messages:
@@ -321,40 +298,10 @@
```
You can also copy `phpunit.xml.dist` file to a custom `phpunit.xml` and put
-these environment variables in it:
-
-```xml
-<?xml version="1.0" encoding="UTF-8"?>
-<phpunit
- bootstrap="./vendor/autoload.php"
- colors="true"
- verbose="true"
->
- <testsuites>
- <testsuite name="ddeboer/imap">
- <directory>./tests/</directory>
- </testsuite>
- </testsuites>
- <filter>
- <whitelist>
- <directory suffix=".php">./src</directory>
- </whitelist>
- </filter>
- <php>
- <env name="IMAP_SERVER_NAME" value="my.imap.server.com" />
- <env name="IMAP_SERVER_PORT" value="60993" />
- <env name="IMAP_USERNAME" value="johndoe" />
- <env name="IMAP_PASSWORD" value="p4ssword" />
- </php>
-</phpunit>
-```
+these environment variables in it.
**WARNING** Tests create new mailboxes without removing them.
-### Running Tests using Docker
-
-If you have Docker installed you can run the tests locally with the following command:
-
```
$ docker-compose run tests
```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/composer.json
index d56ea38..92b4a07 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/composer.json
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/composer.json
@@ -22,23 +22,18 @@
}
],
"require": {
- "php": "^7.3 || ^8.0",
+ "php": "^7.4 || ^8.0",
"ext-iconv": "*",
"ext-imap": "*",
"ext-mbstring": "*"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^2.16.7",
- "laminas/laminas-mail": "^2.12.3",
- "phpstan/phpstan": "^0.12.57",
- "phpstan/phpstan-phpunit": "^0.12.16",
- "phpstan/phpstan-strict-rules": "^0.12.5",
- "phpunit/phpunit": "^9.4.3"
- },
- "config": {
- "platform": {
- "php": "7.3"
- }
+ "friendsofphp/php-cs-fixer": "^2.18.6",
+ "laminas/laminas-mail": "^2.14.0",
+ "phpstan/phpstan": "^0.12.84",
+ "phpstan/phpstan-phpunit": "^0.12.18",
+ "phpstan/phpstan-strict-rules": "^0.12.9",
+ "phpunit/phpunit": "^9.5.4"
},
"autoload": {
"psr-4": {
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Connection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Connection.php
index 4f9f405..d9f2bb6 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Connection.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Connection.php
@@ -9,7 +9,6 @@
use Ddeboer\Imap\Exception\ImapGetmailboxesException;
use Ddeboer\Imap\Exception\ImapNumMsgException;
use Ddeboer\Imap\Exception\ImapQuotaException;
-use Ddeboer\Imap\Exception\InvalidResourceException;
use Ddeboer\Imap\Exception\MailboxDoesNotExistException;
/**
@@ -17,25 +16,16 @@
*/
final class Connection implements ConnectionInterface
{
+ private ImapResourceInterface $resource;
+ private string $server;
/**
- * @var ImapResourceInterface
+ * @var null|MailboxInterface[]
*/
- private $resource;
-
+ private ?array $mailboxes = null;
/**
- * @var string
+ * @var null|array<int|string, \stdClass>
*/
- private $server;
-
- /**
- * @var null|array
- */
- private $mailboxes;
-
- /**
- * @var null|array
- */
- private $mailboxNames;
+ private ?array $mailboxNames = null;
/**
* Constructor.
@@ -48,25 +38,16 @@
$this->server = $server;
}
- /**
- * Get IMAP resource.
- */
public function getResource(): ImapResourceInterface
{
return $this->resource;
}
- /**
- * Delete all messages marked for deletion.
- */
public function expunge(): bool
{
return \imap_expunge($this->resource->getStream());
}
- /**
- * Close connection.
- */
public function close(int $flag = 0): bool
{
$this->resource->clearLastMailboxUsedCache();
@@ -74,9 +55,6 @@
return \imap_close($this->resource->getStream(), $flag);
}
- /**
- * Get Mailbox quota.
- */
public function getQuota(string $root = 'INBOX'): array
{
$errorMessage = null;
@@ -106,14 +84,10 @@
return $return;
}
- /**
- * Get a list of mailboxes (also known as folders).
- *
- * @return MailboxInterface[]
- */
public function getMailboxes(): array
{
$this->initMailboxNames();
+ \assert(null !== $this->mailboxNames);
if (null === $this->mailboxes) {
$this->mailboxes = [];
@@ -125,39 +99,24 @@
return $this->mailboxes;
}
- /**
- * Check that a mailbox with the given name exists.
- *
- * @param string $name Mailbox name
- */
public function hasMailbox(string $name): bool
{
$this->initMailboxNames();
+ \assert(null !== $this->mailboxNames);
return isset($this->mailboxNames[$name]);
}
- /**
- * Get a mailbox by its name.
- *
- * @param string $name Mailbox name
- *
- * @throws MailboxDoesNotExistException If mailbox does not exist
- */
public function getMailbox(string $name): MailboxInterface
{
if (false === $this->hasMailbox($name)) {
throw new MailboxDoesNotExistException(\sprintf('Mailbox name "%s" does not exist', $name));
}
+ \assert(isset($this->mailboxNames[$name]));
return new Mailbox($this->resource, $name, $this->mailboxNames[$name]);
}
- /**
- * Count number of messages not in any mailbox.
- *
- * @return int
- */
public function count()
{
$return = \imap_num_msg($this->resource->getStream());
@@ -169,21 +128,11 @@
return $return;
}
- /**
- * Check if the connection is still active.
- *
- * @throws InvalidResourceException If connection was closed
- */
public function ping(): bool
{
return \imap_ping($this->resource->getStream());
}
- /**
- * Create mailbox.
- *
- * @throws CreateMailboxException
- */
public function createMailbox(string $name): MailboxInterface
{
if (false === \imap_createmailbox($this->resource->getStream(), $this->server . \mb_convert_encoding($name, 'UTF7-IMAP', 'UTF-8'))) {
@@ -196,11 +145,6 @@
return $this->getMailbox($name);
}
- /**
- * Create mailbox.
- *
- * @throws DeleteMailboxException
- */
public function deleteMailbox(MailboxInterface $mailbox): void
{
if (false === \imap_deletemailbox($this->resource->getStream(), $mailbox->getFullEncodedName())) {
@@ -211,9 +155,6 @@
$this->resource->clearLastMailboxUsedCache();
}
- /**
- * Get mailbox names.
- */
private function initMailboxNames(): void
{
if (null !== $this->mailboxNames) {
@@ -227,8 +168,9 @@
}
foreach ($mailboxesInfo as $mailboxInfo) {
- $name = \mb_convert_encoding(\str_replace($this->server, '', $mailboxInfo->name), 'UTF-8', 'UTF7-IMAP');
+ $name = \mb_convert_encoding(\str_replace($this->server, '', $mailboxInfo->name), 'UTF-8', 'UTF7-IMAP');
\assert(\is_string($name));
+
$this->mailboxNames[$name] = $mailboxInfo;
}
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ConnectionInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ConnectionInterface.php
index e76077f..6289339 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ConnectionInterface.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ConnectionInterface.php
@@ -4,6 +4,11 @@
namespace Ddeboer\Imap;
+use Ddeboer\Imap\Exception\CreateMailboxException;
+use Ddeboer\Imap\Exception\DeleteMailboxException;
+use Ddeboer\Imap\Exception\InvalidResourceException;
+use Ddeboer\Imap\Exception\MailboxDoesNotExistException;
+
/**
* A connection to an IMAP server that is authenticated for a user.
*/
@@ -26,11 +31,15 @@
/**
* Check if the connection is still active.
+ *
+ * @throws InvalidResourceException If connection was closed
*/
public function ping(): bool;
/**
* Get Mailbox quota.
+ *
+ * @return array<string, int>
*/
public function getQuota(string $root = 'INBOX'): array;
@@ -52,16 +61,22 @@
* Get a mailbox by its name.
*
* @param string $name Mailbox name
+ *
+ * @throws MailboxDoesNotExistException If mailbox does not exist
*/
public function getMailbox(string $name): MailboxInterface;
/**
* Create mailbox.
+ *
+ * @throws CreateMailboxException
*/
public function createMailbox(string $name): MailboxInterface;
/**
* Delete mailbox.
+ *
+ * @throws DeleteMailboxException
*/
public function deleteMailbox(MailboxInterface $mailbox): void;
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AbstractException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AbstractException.php
index 26c1e58..6537a05 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AbstractException.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AbstractException.php
@@ -6,10 +6,7 @@
abstract class AbstractException extends \RuntimeException
{
- /**
- * @var array
- */
- private static $errorLabels = [
+ private const ERROR_LABELS = [
\E_ERROR => 'E_ERROR',
\E_WARNING => 'E_WARNING',
\E_PARSE => 'E_PARSE',
@@ -27,16 +24,11 @@
\E_USER_DEPRECATED => 'E_USER_DEPRECATED',
];
- /**
- * @param string $message The exception message
- * @param int $code The exception code
- * @param \Throwable $previous The previous exception
- */
final public function __construct(string $message, int $code = 0, \Throwable $previous = null)
{
$errorType = '';
- if (isset(self::$errorLabels[$code])) {
- $errorType = \sprintf('[%s] ', self::$errorLabels[$code]);
+ if (isset(self::ERROR_LABELS[$code])) {
+ $errorType = \sprintf('[%s] ', self::ERROR_LABELS[$code]);
}
$joinString = "\n- ";
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResource.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResource.php
index 60c1617..123ea23 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResource.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResource.php
@@ -13,19 +13,11 @@
final class ImapResource implements ImapResourceInterface
{
/**
- * @var mixed
+ * @var resource
*/
private $resource;
-
- /**
- * @var null|MailboxInterface
- */
- private $mailbox;
-
- /**
- * @var null|string
- */
- private static $lastMailboxUsedCache;
+ private ?MailboxInterface $mailbox = null;
+ private static ?string $lastMailboxUsedCache = null;
/**
* Constructor.
@@ -38,13 +30,6 @@
$this->mailbox = $mailbox;
}
- /**
- * Get IMAP resource stream.
- *
- * @throws InvalidResourceException
- *
- * @return resource
- */
public function getStream()
{
if (false === \is_resource($this->resource) || 'imap' !== \get_resource_type($this->resource)) {
@@ -56,9 +41,6 @@
return $this->resource;
}
- /**
- * Clear last mailbox used cache.
- */
public function clearLastMailboxUsedCache(): void
{
self::$lastMailboxUsedCache = null;
@@ -85,7 +67,7 @@
/**
* Check whether the current mailbox is open.
*
- * @param mixed $resource
+ * @param resource $resource
*/
private static function isMailboxOpen(MailboxInterface $mailbox, $resource): bool
{
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResourceInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResourceInterface.php
index 03c16f7..cf49f6b 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResourceInterface.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResourceInterface.php
@@ -4,11 +4,15 @@
namespace Ddeboer\Imap;
+use Ddeboer\Imap\Exception\InvalidResourceException;
+
interface ImapResourceInterface
{
/**
* Get IMAP resource stream.
*
+ * @throws InvalidResourceException
+ *
* @return resource
*/
public function getStream();
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Mailbox.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Mailbox.php
index 1544aff..2f77799 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Mailbox.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Mailbox.php
@@ -18,20 +18,9 @@
*/
final class Mailbox implements MailboxInterface
{
- /**
- * @var ImapResourceInterface
- */
- private $resource;
-
- /**
- * @var string
- */
- private $name;
-
- /**
- * @var \stdClass
- */
- private $info;
+ private ImapResourceInterface $resource;
+ private string $name;
+ private \stdClass $info;
/**
* Constructor.
@@ -47,17 +36,11 @@
$this->info = $info;
}
- /**
- * Get mailbox decoded name.
- */
public function getName(): string
{
return $this->name;
}
- /**
- * Get mailbox encoded path.
- */
public function getEncodedName(): string
{
/** @var string $name */
@@ -66,35 +49,21 @@
return (string) \preg_replace('/^{.+}/', '', $name);
}
- /**
- * Get mailbox encoded full name.
- */
public function getFullEncodedName(): string
{
return $this->info->name;
}
- /**
- * Get mailbox attributes.
- */
public function getAttributes(): int
{
return $this->info->attributes;
}
- /**
- * Get mailbox delimiter.
- */
public function getDelimiter(): string
{
return $this->info->delimiter;
}
- /**
- * Get number of messages in this mailbox.
- *
- * @return int
- */
public function count()
{
$return = \imap_num_msg($this->resource->getStream());
@@ -106,9 +75,6 @@
return $return;
}
- /**
- * Get Mailbox status.
- */
public function getStatus(int $flags = null): \stdClass
{
$return = \imap_status($this->resource->getStream(), $this->getFullEncodedName(), $flags ?? \SA_ALL);
@@ -120,33 +86,16 @@
return $return;
}
- /**
- * Bulk Set Flag for Messages.
- *
- * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
- * @param array|MessageIterator|string $numbers Message numbers
- */
public function setFlag(string $flag, $numbers): bool
{
return \imap_setflag_full($this->resource->getStream(), $this->prepareMessageIds($numbers), $flag, \ST_UID);
}
- /**
- * Bulk Clear Flag for Messages.
- *
- * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
- * @param array|MessageIterator|string $numbers Message numbers
- */
public function clearFlag(string $flag, $numbers): bool
{
return \imap_clearflag_full($this->resource->getStream(), $this->prepareMessageIds($numbers), $flag, \ST_UID);
}
- /**
- * Get message ids.
- *
- * @param ConditionInterface $search Search expression (optional)
- */
public function getMessages(ConditionInterface $search = null, int $sortCriteria = null, bool $descending = false, string $charset = null): MessageIteratorInterface
{
if (null === $search) {
@@ -199,11 +148,6 @@
return new MessageIterator($this->resource, $messageNumbers);
}
- /**
- * Get message iterator for a sequence.
- *
- * @param string $sequence Message numbers
- */
public function getMessageSequence(string $sequence): MessageIteratorInterface
{
\imap_errors();
@@ -223,54 +167,38 @@
return new MessageIterator($this->resource, $messageNumbers);
}
- /**
- * Get a message by message number.
- *
- * @param int $number Message number
- */
public function getMessage(int $number): MessageInterface
{
return new Message($this->resource, $number);
}
- /**
- * Get messages in this mailbox.
- */
public function getIterator(): MessageIteratorInterface
{
return $this->getMessages();
}
- /**
- * Add a message to the mailbox.
- */
public function addMessage(string $message, string $options = null, DateTimeInterface $internalDate = null): bool
{
$arguments = [
$this->resource->getStream(),
$this->getFullEncodedName(),
$message,
+ $options ?? '',
];
- if (null !== $options) {
- $arguments[] = $options;
- if (null !== $internalDate) {
- $arguments[] = $internalDate->format('d-M-Y H:i:s O');
- }
+ if (null !== $internalDate) {
+ $arguments[] = $internalDate->format('d-M-Y H:i:s O');
}
return \imap_append(...$arguments);
}
- /**
- * Returns a tree of threaded message for the current Mailbox.
- */
public function getThread(): array
{
\set_error_handler(static function (): bool {
return true;
});
- /** @var array|false $tree */
+ /** @var array<string, int>|false $tree */
$tree = \imap_thread($this->resource->getStream(), \SE_UID);
\restore_error_handler();
@@ -278,29 +206,13 @@
return false !== $tree ? $tree : [];
}
- /**
- * Bulk move messages.
- *
- * @param array|MessageIterator|string $numbers Message numbers
- * @param MailboxInterface $mailbox Destination Mailbox to move the messages to
- *
- * @throws \Ddeboer\Imap\Exception\MessageMoveException
- */
public function move($numbers, MailboxInterface $mailbox): void
{
- if (!\imap_mail_move($this->resource->getStream(), $this->prepareMessageIds($numbers), $mailbox->getEncodedName(), \CP_UID)) {
+ if (!\imap_mail_copy($this->resource->getStream(), $this->prepareMessageIds($numbers), $mailbox->getEncodedName(), \CP_UID | \CP_MOVE)) {
throw new MessageMoveException(\sprintf('Messages cannot be moved to "%s"', $mailbox->getName()));
}
}
- /**
- * Bulk copy messages.
- *
- * @param array|MessageIterator|string $numbers Message numbers
- * @param MailboxInterface $mailbox Destination Mailbox to copy the messages to
- *
- * @throws \Ddeboer\Imap\Exception\MessageCopyException
- */
public function copy($numbers, MailboxInterface $mailbox): void
{
if (!\imap_mail_copy($this->resource->getStream(), $this->prepareMessageIds($numbers), $mailbox->getEncodedName(), \CP_UID)) {
@@ -311,7 +223,7 @@
/**
* Prepare message ids for the use with bulk functions.
*
- * @param array|MessageIterator|string $messageIds Message numbers
+ * @param array<int, int|string>|MessageIterator|string $messageIds Message numbers
*/
private function prepareMessageIds($messageIds): string
{
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MailboxInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MailboxInterface.php
index efe432d..067bdc2 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MailboxInterface.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MailboxInterface.php
@@ -5,10 +5,13 @@
namespace Ddeboer\Imap;
use DateTimeInterface;
+use Ddeboer\Imap\Message\PartInterface;
use Ddeboer\Imap\Search\ConditionInterface;
/**
* An IMAP mailbox (commonly referred to as a 'folder').
+ *
+ * @extends \IteratorAggregate<int, MessageInterface>
*/
interface MailboxInterface extends \Countable, \IteratorAggregate
{
@@ -45,16 +48,16 @@
/**
* Bulk Set Flag for Messages.
*
- * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
- * @param array|MessageIterator|string $numbers Message numbers
+ * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
+ * @param array<int, int|string>|MessageIterator|string $numbers Message numbers
*/
public function setFlag(string $flag, $numbers): bool;
/**
* Bulk Clear Flag for Messages.
*
- * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
- * @param array|MessageIterator|string $numbers Message numbers
+ * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
+ * @param array<int, int|string>|MessageIterator|string $numbers Message numbers
*/
public function clearFlag(string $flag, $numbers): bool;
@@ -76,6 +79,8 @@
* Get a message by message number.
*
* @param int $number Message number
+ *
+ * @return MessageInterface<PartInterface>
*/
public function getMessage(int $number): MessageInterface;
@@ -91,14 +96,16 @@
/**
* Returns a tree of threaded message for the current Mailbox.
+ *
+ * @return array<string, int>
*/
public function getThread(): array;
/**
* Bulk move messages.
*
- * @param array|MessageIterator|string $numbers Message numbers
- * @param MailboxInterface $mailbox Destination Mailbox to move the messages to
+ * @param array<int, int|string>|MessageIterator|string $numbers Message numbers
+ * @param MailboxInterface $mailbox Destination Mailbox to move the messages to
*
* @throws \Ddeboer\Imap\Exception\MessageMoveException
*/
@@ -107,8 +114,8 @@
/**
* Bulk copy messages.
*
- * @param array|MessageIterator|string $numbers Message numbers
- * @param MailboxInterface $mailbox Destination Mailbox to copy the messages to
+ * @param array<int, int|string>|MessageIterator|string $numbers Message numbers
+ * @param MailboxInterface $mailbox Destination Mailbox to copy the messages to
*
* @throws \Ddeboer\Imap\Exception\MessageCopyException
*/
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message.php
index 843ce61..1a9d16e 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message.php
@@ -18,35 +18,12 @@
*/
final class Message extends Message\AbstractMessage implements MessageInterface
{
- /**
- * @var bool
- */
- private $messageNumberVerified = false;
-
- /**
- * @var int
- */
- private $imapMsgNo = 0;
-
- /**
- * @var bool
- */
- private $structureLoaded = false;
-
- /**
- * @var null|Message\Headers
- */
- private $headers;
-
- /**
- * @var null|string
- */
- private $rawHeaders;
-
- /**
- * @var null|string
- */
- private $rawMessage;
+ private bool $messageNumberVerified = false;
+ private int $imapMsgNo = 0;
+ private bool $structureLoaded = false;
+ private ?Message\Headers $headers = null;
+ private ?string $rawHeaders = null;
+ private ?string $rawMessage = null;
/**
* Constructor.
@@ -59,9 +36,6 @@
parent::__construct($resource, $messageNumber, '1', new \stdClass());
}
- /**
- * Lazy load structure.
- */
protected function lazyLoadStructure(): void
{
if (true === $this->structureLoaded) {
@@ -99,9 +73,6 @@
$this->setStructure($structure);
}
- /**
- * Ensure message exists.
- */
protected function assertMessageExists(int $messageNumber): void
{
if (true === $this->messageNumberVerified) {
@@ -138,9 +109,6 @@
return $this->imapMsgNo;
}
- /**
- * Get raw message headers.
- */
public function getRawHeaders(): string
{
if (null === $this->rawHeaders) {
@@ -156,11 +124,6 @@
return $this->rawHeaders;
}
- /**
- * Get the raw message, including all headers, parts, etc. unencoded and unparsed.
- *
- * @return string the raw message
- */
public function getRawMessage(): string
{
if (null === $this->rawMessage) {
@@ -170,9 +133,6 @@
return $this->rawMessage;
}
- /**
- * Get message headers.
- */
public function getHeaders(): Message\Headers
{
if (null === $this->headers) {
@@ -198,67 +158,44 @@
$this->headers = null;
}
- /**
- * Get message recent flag value (from headers).
- */
public function isRecent(): ?string
{
- return $this->getHeaders()->get('recent');
+ $recent = $this->getHeaders()->get('recent');
+ \assert(null === $recent || \is_string($recent));
+
+ return $recent;
}
- /**
- * Get message unseen flag value (from headers).
- */
public function isUnseen(): bool
{
return 'U' === $this->getHeaders()->get('unseen');
}
- /**
- * Get message flagged flag value (from headers).
- */
public function isFlagged(): bool
{
return 'F' === $this->getHeaders()->get('flagged');
}
- /**
- * Get message answered flag value (from headers).
- */
public function isAnswered(): bool
{
return 'A' === $this->getHeaders()->get('answered');
}
- /**
- * Get message deleted flag value (from headers).
- */
public function isDeleted(): bool
{
return 'D' === $this->getHeaders()->get('deleted');
}
- /**
- * Get message draft flag value (from headers).
- */
public function isDraft(): bool
{
return 'X' === $this->getHeaders()->get('draft');
}
- /**
- * Has the message been marked as read?
- */
public function isSeen(): bool
{
return 'N' !== $this->getHeaders()->get('recent') && 'U' !== $this->getHeaders()->get('unseen');
}
- /**
- * Mark message as seen.
- *
- * @deprecated since version 1.1, to be removed in 2.0
- */
public function maskAsSeen(): bool
{
\trigger_error(\sprintf('%s is deprecated and will be removed in 2.0. Use %s::markAsSeen instead.', __METHOD__, __CLASS__), \E_USER_DEPRECATED);
@@ -266,19 +203,11 @@
return $this->markAsSeen();
}
- /**
- * Mark message as seen.
- */
public function markAsSeen(): bool
{
return $this->setFlag('\\Seen');
}
- /**
- * Move message to another mailbox.
- *
- * @throws MessageCopyException
- */
public function copy(MailboxInterface $mailbox): void
{
// 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header
@@ -289,11 +218,6 @@
}
}
- /**
- * Move message to another mailbox.
- *
- * @throws MessageMoveException
- */
public function move(MailboxInterface $mailbox): void
{
// 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header
@@ -304,11 +228,6 @@
}
}
- /**
- * Delete message.
- *
- * @throws MessageDeleteException
- */
public function delete(): void
{
// 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header
@@ -319,11 +238,6 @@
}
}
- /**
- * Undelete message.
- *
- * @throws MessageUndeleteException
- */
public function undelete(): void
{
// 'deleted' header changed, force to reload headers, would be better to set deleted flag to false on header
@@ -333,11 +247,6 @@
}
}
- /**
- * Set Flag Message.
- *
- * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
- */
public function setFlag(string $flag): bool
{
$result = \imap_setflag_full($this->resource->getStream(), (string) $this->getNumber(), $flag, \ST_UID);
@@ -347,11 +256,6 @@
return $result;
}
- /**
- * Clear Flag Message.
- *
- * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
- */
public function clearFlag(string $flag): bool
{
$result = \imap_clearflag_full($this->resource->getStream(), (string) $this->getNumber(), $flag, \ST_UID);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php
index 5d67e90..0f022cc 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php
@@ -9,9 +9,9 @@
abstract class AbstractMessage extends AbstractPart
{
/**
- * @var null|array
+ * @var null|Attachment[]
*/
- private $attachments;
+ private ?array $attachments = null;
/**
* Get message headers.
@@ -25,7 +25,10 @@
*/
final public function getId(): ?string
{
- return $this->getHeaders()->get('message_id');
+ $messageId = $this->getHeaders()->get('message_id');
+ \assert(null === $messageId || \is_string($messageId));
+
+ return $messageId;
}
/**
@@ -34,6 +37,7 @@
final public function getFrom(): ?EmailAddress
{
$from = $this->getHeaders()->get('from');
+ \assert(null === $from || \is_array($from));
return null !== $from ? $this->decodeEmailAddress($from[0]) : null;
}
@@ -45,7 +49,10 @@
*/
final public function getTo(): array
{
- return $this->decodeEmailAddresses($this->getHeaders()->get('to') ?: []);
+ $emails = $this->getHeaders()->get('to');
+ \assert(null === $emails || \is_array($emails));
+
+ return $this->decodeEmailAddresses($emails ?? []);
}
/**
@@ -55,7 +62,10 @@
*/
final public function getCc(): array
{
- return $this->decodeEmailAddresses($this->getHeaders()->get('cc') ?: []);
+ $emails = $this->getHeaders()->get('cc');
+ \assert(null === $emails || \is_array($emails));
+
+ return $this->decodeEmailAddresses($emails ?? []);
}
/**
@@ -65,7 +75,10 @@
*/
final public function getBcc(): array
{
- return $this->decodeEmailAddresses($this->getHeaders()->get('bcc') ?: []);
+ $emails = $this->getHeaders()->get('bcc');
+ \assert(null === $emails || \is_array($emails));
+
+ return $this->decodeEmailAddresses($emails ?? []);
}
/**
@@ -75,7 +88,10 @@
*/
final public function getReplyTo(): array
{
- return $this->decodeEmailAddresses($this->getHeaders()->get('reply_to') ?: []);
+ $emails = $this->getHeaders()->get('reply_to');
+ \assert(null === $emails || \is_array($emails));
+
+ return $this->decodeEmailAddresses($emails ?? []);
}
/**
@@ -85,7 +101,10 @@
*/
final public function getSender(): array
{
- return $this->decodeEmailAddresses($this->getHeaders()->get('sender') ?: []);
+ $emails = $this->getHeaders()->get('sender');
+ \assert(null === $emails || \is_array($emails));
+
+ return $this->decodeEmailAddresses($emails ?? []);
}
/**
@@ -95,7 +114,10 @@
*/
final public function getReturnPath(): array
{
- return $this->decodeEmailAddresses($this->getHeaders()->get('return_path') ?: []);
+ $emails = $this->getHeaders()->get('return_path');
+ \assert(null === $emails || \is_array($emails));
+
+ return $this->decodeEmailAddresses($emails ?? []);
}
/**
@@ -137,7 +159,10 @@
*/
final public function getSize()
{
- return $this->getHeaders()->get('size');
+ $size = $this->getHeaders()->get('size');
+ \assert(null === $size || \is_int($size) || \is_string($size));
+
+ return $size;
}
/**
@@ -145,25 +170,34 @@
*/
final public function getSubject(): ?string
{
- return $this->getHeaders()->get('subject');
+ $subject = $this->getHeaders()->get('subject');
+ \assert(null === $subject || \is_string($subject));
+
+ return $subject;
}
/**
* Get message In-Reply-To (from headers).
+ *
+ * @return string[]
*/
final public function getInReplyTo(): array
{
$inReplyTo = $this->getHeaders()->get('in_reply_to');
+ \assert(null === $inReplyTo || \is_string($inReplyTo));
return null !== $inReplyTo ? \explode(' ', $inReplyTo) : [];
}
/**
* Get message References (from headers).
+ *
+ * @return string[]
*/
final public function getReferences(): array
{
$references = $this->getHeaders()->get('references');
+ \assert(null === $references || \is_string($references));
return null !== $references ? \explode(' ', $references) : [];
}
@@ -222,6 +256,11 @@
return $this->attachments;
}
+ /**
+ * @param PartInterface<PartInterface> $part
+ *
+ * @return Attachment[]
+ */
private static function gatherAttachments(PartInterface $part): array
{
$attachments = [];
@@ -247,6 +286,8 @@
/**
* @param \stdClass[] $addresses
+ *
+ * @return EmailAddress[]
*/
private function decodeEmailAddresses(array $addresses): array
{
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractPart.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractPart.php
index ab13eb0..0ab0ca5 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractPart.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractPart.php
@@ -14,95 +14,7 @@
*/
abstract class AbstractPart implements PartInterface
{
- /**
- * @var ImapResourceInterface
- */
- protected $resource;
-
- /**
- * @var bool
- */
- private $structureParsed = false;
-
- /**
- * @var array
- */
- private $parts = [];
-
- /**
- * @var string
- */
- private $partNumber;
-
- /**
- * @var int
- */
- private $messageNumber;
-
- /**
- * @var \stdClass
- */
- private $structure;
-
- /**
- * @var Parameters
- */
- private $parameters;
-
- /**
- * @var null|string
- */
- private $type;
-
- /**
- * @var null|string
- */
- private $subtype;
-
- /**
- * @var null|string
- */
- private $encoding;
-
- /**
- * @var null|string
- */
- private $disposition;
-
- /**
- * @var null|string
- */
- private $description;
-
- /**
- * @var null|string
- */
- private $bytes;
-
- /**
- * @var null|string
- */
- private $lines;
-
- /**
- * @var null|string
- */
- private $content;
-
- /**
- * @var null|string
- */
- private $decodedContent;
-
- /**
- * @var int
- */
- private $key = 0;
-
- /**
- * @var array
- */
- private static $typesMap = [
+ private const TYPES_MAP = [
\TYPETEXT => self::TYPE_TEXT,
\TYPEMULTIPART => self::TYPE_MULTIPART,
\TYPEMESSAGE => self::TYPE_MESSAGE,
@@ -114,10 +26,7 @@
\TYPEOTHER => self::TYPE_OTHER,
];
- /**
- * @var array
- */
- private static $encodingsMap = [
+ private const ENCODINGS_MAP = [
\ENC7BIT => self::ENCODING_7BIT,
\ENC8BIT => self::ENCODING_8BIT,
\ENCBINARY => self::ENCODING_BINARY,
@@ -125,16 +34,35 @@
\ENCQUOTEDPRINTABLE => self::ENCODING_QUOTED_PRINTABLE,
];
- /**
- * @var array
- */
- private static $attachmentKeys = [
+ private const ATTACHMENT_KEYS = [
'name' => true,
'filename' => true,
'name*' => true,
'filename*' => true,
];
+ protected ImapResourceInterface $resource;
+ private bool $structureParsed = false;
+ /**
+ * @var AbstractPart[]
+ */
+ private array $parts = [];
+ private string $partNumber;
+ private int $messageNumber;
+ private \stdClass $structure;
+ private Parameters $parameters;
+ private ?string $type = null;
+ private ?string $subtype = null;
+ private ?string $encoding = null;
+ private ?string $disposition = null;
+ private ?string $description = null;
+ /** @var null|int|string */
+ private $bytes;
+ private ?string $lines = null;
+ private ?string $content = null;
+ private ?string $decodedContent = null;
+ private int $key = 0;
+
/**
* Constructor.
*
@@ -155,9 +83,6 @@
$this->setStructure($structure);
}
- /**
- * Get message number (from headers).
- */
final public function getNumber(): int
{
$this->assertMessageExists($this->messageNumber);
@@ -180,9 +105,6 @@
$this->structure = $structure;
}
- /**
- * Part structure.
- */
final public function getStructure(): \stdClass
{
$this->lazyLoadStructure();
@@ -197,9 +119,6 @@
{
}
- /**
- * Part parameters.
- */
final public function getParameters(): Parameters
{
$this->lazyParseStructure();
@@ -207,19 +126,16 @@
return $this->parameters;
}
- /**
- * Part charset.
- */
final public function getCharset(): ?string
{
$this->lazyParseStructure();
- return $this->parameters->get('charset') ?: null;
+ $charset = $this->parameters->get('charset');
+ \assert(null === $charset || \is_string($charset));
+
+ return '' !== $charset ? $charset : null;
}
- /**
- * Part type.
- */
final public function getType(): ?string
{
$this->lazyParseStructure();
@@ -227,9 +143,6 @@
return $this->type;
}
- /**
- * Part subtype.
- */
final public function getSubtype(): ?string
{
$this->lazyParseStructure();
@@ -237,9 +150,6 @@
return $this->subtype;
}
- /**
- * Part encoding.
- */
final public function getEncoding(): ?string
{
$this->lazyParseStructure();
@@ -247,9 +157,6 @@
return $this->encoding;
}
- /**
- * Part disposition.
- */
final public function getDisposition(): ?string
{
$this->lazyParseStructure();
@@ -257,9 +164,6 @@
return $this->disposition;
}
- /**
- * Part description.
- */
final public function getDescription(): ?string
{
$this->lazyParseStructure();
@@ -267,11 +171,6 @@
return $this->description;
}
- /**
- * Part bytes.
- *
- * @return null|int|string
- */
final public function getBytes()
{
$this->lazyParseStructure();
@@ -279,9 +178,6 @@
return $this->bytes;
}
- /**
- * Part lines.
- */
final public function getLines(): ?string
{
$this->lazyParseStructure();
@@ -289,9 +185,6 @@
return $this->lines;
}
- /**
- * Get raw part content.
- */
final public function getContent(): string
{
if (null === $this->content) {
@@ -309,17 +202,11 @@
return $this->partNumber;
}
- /**
- * Get part number.
- */
final public function getPartNumber(): string
{
return $this->partNumber;
}
- /**
- * Get decoded part content.
- */
final public function getDecodedContent(): string
{
if (null === $this->decodedContent) {
@@ -369,11 +256,6 @@
return $return;
}
- /**
- * Get an array of all parts for this message.
- *
- * @return PartInterface[]
- */
final public function getParts(): array
{
$this->lazyParseStructure();
@@ -393,21 +275,11 @@
return $this->parts[$this->key];
}
- /**
- * Get current child part.
- *
- * @return \RecursiveIterator
- */
final public function getChildren()
{
return $this->current();
}
- /**
- * Get current child part.
- *
- * @return bool
- */
final public function hasChildren()
{
$this->lazyParseStructure();
@@ -416,8 +288,6 @@
}
/**
- * Get current part key.
- *
* @return int
*/
final public function key()
@@ -425,31 +295,16 @@
return $this->key;
}
- /**
- * Move to next part.
- *
- * @return void
- */
final public function next()
{
++$this->key;
}
- /**
- * Reset part key.
- *
- * @return void
- */
final public function rewind()
{
$this->key = 0;
}
- /**
- * Check if current part is a valid one.
- *
- * @return bool
- */
final public function valid()
{
$this->lazyParseStructure();
@@ -469,10 +324,10 @@
$this->lazyLoadStructure();
- $this->type = self::$typesMap[$this->structure->type] ?? self::TYPE_UNKNOWN;
+ $this->type = self::TYPES_MAP[$this->structure->type] ?? self::TYPE_UNKNOWN;
// In our context, \ENCOTHER is as useful as an unknown encoding
- $this->encoding = self::$encodingsMap[$this->structure->encoding] ?? self::ENCODING_UNKNOWN;
+ $this->encoding = self::ENCODINGS_MAP[$this->structure->encoding] ?? self::ENCODING_UNKNOWN;
if (isset($this->structure->subtype)) {
$this->subtype = $this->structure->subtype;
}
@@ -527,7 +382,7 @@
*/
private static function isAttachment(\stdClass $part): bool
{
- if (isset(self::$typesMap[$part->type]) && self::TYPE_MULTIPART === self::$typesMap[$part->type]) {
+ if (isset(self::TYPES_MAP[$part->type]) && self::TYPE_MULTIPART === self::TYPES_MAP[$part->type]) {
return false;
}
@@ -549,7 +404,7 @@
// Attachment without Content-Disposition header
if ($part->ifparameters) {
foreach ($part->parameters as $parameter) {
- if (isset(self::$attachmentKeys[\strtolower($parameter->attribute)])) {
+ if (isset(self::ATTACHMENT_KEYS[\strtolower($parameter->attribute)])) {
return true;
}
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Attachment.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Attachment.php
index bd76769..b134b8d 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Attachment.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Attachment.php
@@ -11,43 +11,33 @@
*/
final class Attachment extends AbstractPart implements AttachmentInterface
{
- /**
- * Get attachment filename.
- */
public function getFilename(): ?string
{
- return $this->getParameters()->get('filename')
- ?: $this->getParameters()->get('name');
+ $filename = $this->getParameters()->get('filename');
+ if (null === $filename || '' === $filename) {
+ $filename = $this->getParameters()->get('name');
+ }
+ \assert(null === $filename || \is_string($filename));
+
+ return $filename;
}
- /**
- * Get attachment file size.
- *
- * @return null|int Number of bytes
- */
public function getSize()
{
$size = $this->getParameters()->get('size');
if (\is_numeric($size)) {
$size = (int) $size;
}
+ \assert(null === $size || \is_int($size));
return $size;
}
- /**
- * Is this attachment also an Embedded Message?
- */
public function isEmbeddedMessage(): bool
{
return self::TYPE_MESSAGE === $this->getType();
}
- /**
- * Return embedded message.
- *
- * @throws NotEmbeddedMessageException
- */
public function getEmbeddedMessage(): EmbeddedMessageInterface
{
if (!$this->isEmbeddedMessage()) {
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php
index 0d20f44..286e188 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php
@@ -4,6 +4,8 @@
namespace Ddeboer\Imap\Message;
+use Ddeboer\Imap\Exception\NotEmbeddedMessageException;
+
/**
* An e-mail attachment.
*/
@@ -28,6 +30,10 @@
/**
* Return embedded message.
+ *
+ * @throws NotEmbeddedMessageException
+ *
+ * @return EmbeddedMessageInterface<PartInterface>
*/
public function getEmbeddedMessage(): EmbeddedMessageInterface;
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/BasicMessageInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/BasicMessageInterface.php
index 20e6b1a..83dbd17 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/BasicMessageInterface.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/BasicMessageInterface.php
@@ -96,11 +96,15 @@
/**
* Get message In-Reply-To (from headers).
+ *
+ * @return string[]
*/
public function getInReplyTo(): array;
/**
* Get message References (from headers).
+ *
+ * @return string[]
*/
public function getReferences(): array;
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmailAddress.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmailAddress.php
index b88e0f9..9f60fb1 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmailAddress.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmailAddress.php
@@ -9,25 +9,10 @@
*/
final class EmailAddress
{
- /**
- * @var string
- */
- private $mailbox;
-
- /**
- * @var null|string
- */
- private $hostname;
-
- /**
- * @var null|string
- */
- private $name;
-
- /**
- * @var null|string
- */
- private $address;
+ private string $mailbox;
+ private ?string $hostname;
+ private ?string $name;
+ private ?string $address;
public function __construct(string $mailbox, string $hostname = null, string $name = null)
{
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php
index 243cff6..20d9715 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php
@@ -6,24 +6,10 @@
final class EmbeddedMessage extends AbstractMessage implements EmbeddedMessageInterface
{
- /**
- * @var null|Headers
- */
- private $headers;
+ private ?Headers $headers = null;
+ private ?string $rawHeaders = null;
+ private ?string $rawMessage = null;
- /**
- * @var null|string
- */
- private $rawHeaders;
-
- /**
- * @var null|string
- */
- private $rawMessage;
-
- /**
- * Get message headers.
- */
public function getHeaders(): Headers
{
if (null === $this->headers) {
@@ -33,9 +19,6 @@
return $this->headers;
}
- /**
- * Get raw message headers.
- */
public function getRawHeaders(): string
{
if (null === $this->rawHeaders) {
@@ -46,11 +29,6 @@
return $this->rawHeaders;
}
- /**
- * Get the raw message, including all headers, parts, etc. unencoded and unparsed.
- *
- * @return string the raw message
- */
public function getRawMessage(): string
{
if (null === $this->rawMessage) {
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Headers.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Headers.php
index f76fec3..0dc6352 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Headers.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Headers.php
@@ -4,14 +4,8 @@
namespace Ddeboer\Imap\Message;
-/**
- * Collection of message headers.
- */
final class Headers extends Parameters
{
- /**
- * Constructor.
- */
public function __construct(\stdClass $headers)
{
parent::__construct();
@@ -27,7 +21,7 @@
/**
* Get header.
*
- * @return mixed
+ * @return null|int|\stdClass[]|string
*/
public function get(string $key)
{
@@ -37,14 +31,16 @@
/**
* Parse header.
*
- * @param mixed $value
+ * @param int|\stdClass[]|string $value
*
- * @return mixed
+ * @return int|\stdClass[]|string
*/
private function parseHeader(string $key, $value)
{
switch ($key) {
case 'msgno':
+ \assert(\is_string($value));
+
return (int) $value;
case 'from':
case 'to':
@@ -53,6 +49,7 @@
case 'reply_to':
case 'sender':
case 'return_path':
+ \assert(\is_array($value));
/** @var \stdClass $address */
foreach ($value as $address) {
if (isset($address->mailbox)) {
@@ -64,6 +61,8 @@
return $value;
case 'date':
case 'subject':
+ \assert(\is_string($value));
+
return $this->decode($value);
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Parameters.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Parameters.php
index 2f7d8a1..37ed816 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Parameters.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Parameters.php
@@ -4,23 +4,22 @@
namespace Ddeboer\Imap\Message;
+/**
+ * @extends \ArrayIterator<int|string, int|string|\stdClass[]>
+ */
class Parameters extends \ArrayIterator
{
/**
- * @var array
+ * @var array<string, string>
*/
- private static $attachmentCustomKeys = [
+ private static array $attachmentCustomKeys = [
'name*' => 'name',
'filename*' => 'filename',
];
- public function __construct(array $parameters = [])
- {
- parent::__construct();
-
- $this->add($parameters);
- }
-
+ /**
+ * @param \stdClass[] $parameters
+ */
public function add(array $parameters = []): void
{
foreach ($parameters as $parameter) {
@@ -34,16 +33,13 @@
}
/**
- * @return mixed
+ * @return null|int|\stdClass[]|string
*/
public function get(string $key)
{
return $this[$key] ?? null;
}
- /**
- * Decode value.
- */
final protected function decode(string $value): string
{
$parts = \imap_mime_header_decode($value);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Transcoder.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Transcoder.php
index ee02a15..bd439e0 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Transcoder.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Transcoder.php
@@ -9,14 +9,12 @@
final class Transcoder
{
/**
- * @var array
- *
* @see https://encoding.spec.whatwg.org/#encodings
* @see https://dxr.mozilla.org/mozilla-central/source/dom/encoding/labelsencodings.properties
* @see https://dxr.mozilla.org/mozilla1.9.1/source/intl/uconv/src/charsetalias.properties
* @see https://msdn.microsoft.com/en-us/library/cc194829.aspx
*/
- private static $charsetAliases = [
+ private const CHARSET_ALIASES = [
'128' => 'Shift_JIS',
'129' => 'EUC-KR',
'134' => 'GB2312',
@@ -252,6 +250,7 @@
'x-iso-10646-ucs-2-le' => 'UTF-16LE',
'x-iso-10646-ucs-4-be' => 'UTF-32BE',
'x-iso-10646-ucs-4-le' => 'UTF-32LE',
+ 'x-mac-ce' => 'windows-1250',
'x-sjis' => 'Shift_JIS',
'x-unicode-2-0-utf-7' => 'UTF-7',
'x-x-big5' => 'Big5',
@@ -282,8 +281,8 @@
$originalFromCharset = $fromCharset;
$lowercaseFromCharset = \strtolower($fromCharset);
- if (isset(self::$charsetAliases[$lowercaseFromCharset])) {
- $fromCharset = self::$charsetAliases[$lowercaseFromCharset];
+ if (isset(self::CHARSET_ALIASES[$lowercaseFromCharset])) {
+ $fromCharset = self::CHARSET_ALIASES[$lowercaseFromCharset];
}
\set_error_handler(static function (): bool {
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageInterface.php
index eda8ab6..e8fe5f7 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageInterface.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageInterface.php
@@ -4,6 +4,11 @@
namespace Ddeboer\Imap;
+use Ddeboer\Imap\Exception\MessageCopyException;
+use Ddeboer\Imap\Exception\MessageDeleteException;
+use Ddeboer\Imap\Exception\MessageMoveException;
+use Ddeboer\Imap\Exception\MessageUndeleteException;
+
/**
* An IMAP message (e-mail).
*/
@@ -63,21 +68,29 @@
/**
* Move message to another mailbox.
+ *
+ * @throws MessageCopyException
*/
public function copy(MailboxInterface $mailbox): void;
/**
* Move message to another mailbox.
+ *
+ * @throws MessageMoveException
*/
public function move(MailboxInterface $mailbox): void;
/**
* Delete message.
+ *
+ * @throws MessageDeleteException
*/
public function delete(): void;
/**
* Undelete message.
+ *
+ * @throws MessageUndeleteException
*/
public function undelete(): void;
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIterator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIterator.php
index c617478..48d87ee 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIterator.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIterator.php
@@ -4,18 +4,20 @@
namespace Ddeboer\Imap;
+use Ddeboer\Imap\Message\PartInterface;
+
+/**
+ * @extends \ArrayIterator<int, MessageInterface>
+ */
final class MessageIterator extends \ArrayIterator implements MessageIteratorInterface
{
- /**
- * @var ImapResourceInterface
- */
- private $resource;
+ private ImapResourceInterface $resource;
/**
* Constructor.
*
* @param ImapResourceInterface $resource IMAP resource
- * @param array $messageNumbers Array of message numbers
+ * @param int[] $messageNumbers Array of message numbers
*/
public function __construct(ImapResourceInterface $resource, array $messageNumbers)
{
@@ -26,6 +28,8 @@
/**
* Get current message.
+ *
+ * @return MessageInterface<PartInterface>
*/
public function current(): MessageInterface
{
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php
index a9d7988..36a7943 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php
@@ -4,10 +4,17 @@
namespace Ddeboer\Imap;
+use Ddeboer\Imap\Message\PartInterface;
+
+/**
+ * @extends \Iterator<MessageInterface>
+ */
interface MessageIteratorInterface extends \Iterator
{
/**
* Get current message.
+ *
+ * @return MessageInterface<PartInterface>
*/
public function current(): MessageInterface;
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractDate.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractDate.php
index cdd7312..61bd05e 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractDate.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractDate.php
@@ -13,17 +13,13 @@
{
/**
* Format for dates to be sent to the IMAP server.
- *
- * @var string
*/
- private $dateFormat;
+ private string $dateFormat;
/**
* The date to be used for the condition.
- *
- * @var DateTimeInterface
*/
- private $date;
+ private DateTimeInterface $date;
/**
* Constructor.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractText.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractText.php
index 69b2516..8b605ce 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractText.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractText.php
@@ -12,10 +12,8 @@
{
/**
* Text to be used for the condition.
- *
- * @var string
*/
- private $text;
+ private string $text;
/**
* Constructor.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/LogicalOperator/OrConditions.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/LogicalOperator/OrConditions.php
index bfebddd..01e7d86 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/LogicalOperator/OrConditions.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/LogicalOperator/OrConditions.php
@@ -15,10 +15,13 @@
/**
* The conditions that together represent the expression.
*
- * @var array
+ * @var ConditionInterface[]
*/
- private $conditions = [];
+ private array $conditions = [];
+ /**
+ * @param ConditionInterface[] $conditions
+ */
public function __construct(array $conditions)
{
foreach ($conditions as $condition) {
@@ -30,6 +33,8 @@
* Adds a new condition to the expression.
*
* @param ConditionInterface $condition the condition to be added
+ *
+ * @return void
*/
private function addCondition(ConditionInterface $condition)
{
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/RawExpression.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/RawExpression.php
index cc6a465..deda65d 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/RawExpression.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/RawExpression.php
@@ -11,10 +11,8 @@
{
/**
* Text to be used for the condition.
- *
- * @var string
*/
- private $expression;
+ private string $expression;
/**
* @param string $expression text for the condition
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/SearchExpression.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/SearchExpression.php
index e89d49e..db95531 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/SearchExpression.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/SearchExpression.php
@@ -14,9 +14,9 @@
/**
* The conditions that together represent the expression.
*
- * @var array
+ * @var ConditionInterface[]
*/
- private $conditions = [];
+ private array $conditions = [];
/**
* Adds a new condition to the expression.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Server.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Server.php
index 7412f00..41a953d 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Server.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Server.php
@@ -12,46 +12,26 @@
*/
final class Server implements ServerInterface
{
+ private string $hostname;
+ private string $port;
+ private string $flags;
/**
- * @var string Internet domain name or bracketed IP address of server
+ * @var mixed[]
*/
- private $hostname;
-
- /**
- * @var string TCP port number
- */
- private $port;
-
- /**
- * @var string Optional flags
- */
- private $flags;
-
- /**
- * @var array
- */
- private $parameters;
-
- /**
- * @var int Connection options
- */
- private $options;
-
- /**
- * @var int Retries number
- */
- private $retries;
+ private array $parameters;
+ private int $options;
+ private int $retries;
/**
* Constructor.
*
- * @param string $hostname Internet domain name or bracketed IP address
- * of server
- * @param string $port TCP port number
- * @param string $flags Optional flags
- * @param array $parameters Connection parameters
- * @param int $options Connection options
- * @param int $retries Retries number
+ * @param string $hostname Internet domain name or bracketed IP address
+ * of server
+ * @param string $port TCP port number
+ * @param string $flags Optional flags
+ * @param mixed[] $parameters Connection parameters
+ * @param int $options Connection options
+ * @param int $retries Retries number
*/
public function __construct(
string $hostname,
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Test/RawMessageIterator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Test/RawMessageIterator.php
index 08500b6..b895f8a 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Test/RawMessageIterator.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Test/RawMessageIterator.php
@@ -4,14 +4,20 @@
namespace Ddeboer\Imap\Test;
+use Ddeboer\Imap\Message\PartInterface;
use Ddeboer\Imap\MessageInterface;
use Ddeboer\Imap\MessageIteratorInterface;
/**
* A MessageIterator to be used in a mocked environment.
+ *
+ * @extends \ArrayIterator<int, MessageInterface>
*/
final class RawMessageIterator extends \ArrayIterator implements MessageIteratorInterface
{
+ /**
+ * @return MessageInterface<PartInterface>
+ */
public function current(): MessageInterface
{
return parent::current();
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.gitattributes b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.gitattributes
new file mode 100644
index 0000000..2a0e9d2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.gitattributes
@@ -0,0 +1 @@
+tests/ export-ignore
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/FUNDING.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/FUNDING.yml
new file mode 100644
index 0000000..ad129a4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+# These are supported funding model platforms
+
+github: [stevebauman]
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/bug_report.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..a56a2af
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,15 @@
+---
+name: Bug report
+about: Create a report to help improve LdapRecord
+title: "[Bug]"
+labels: bug
+assignees: ''
+
+---
+
+<!-- Please update the below information with your environment. -->
+**Environment:**
+ - LDAP Server Type: [e.g. ActiveDirectory / OpenLDAP / FreeIPA]
+ - PHP Version: [e.g. 7.3 / 7.4 / 8.0]
+
+**Describe the bug:**
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/feature_request.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..68e5bcd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,10 @@
+---
+name: Feature request
+about: Suggest an idea for LdapRecord
+title: "[Feature]"
+labels: enhancement
+assignees: ''
+
+---
+
+**Describe the feature you'd like:**
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/support---help-request.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/support---help-request.md
new file mode 100644
index 0000000..230916c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/support---help-request.md
@@ -0,0 +1,17 @@
+---
+name: Support / help request
+about: Request help using LdapRecord (requires sponsorship)
+title: "[Support]"
+labels: question
+assignees: ''
+
+---
+
+<!-- ISSUE WILL BE CLOSED WITHOUT SPONSORSHIP: -->
+<!-- https://github.com/sponsors/stevebauman -->
+<!-- Thank you for your understanding. -->
+
+<!-- Please update the below information with your environment. -->
+**Environment:**
+ - LDAP Server Type: [e.g. ActiveDirectory / OpenLDAP / FreeIPA]
+ - PHP Version: [e.g. 7.3 / 7.4 / 8.0]
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml
new file mode 100644
index 0000000..ba00218
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml
@@ -0,0 +1,41 @@
+name: run-tests
+
+on:
+ push:
+ pull_request:
+ schedule:
+ - cron: "0 0 * * *"
+
+jobs:
+ run-tests:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest, windows-latest]
+ php: [8.0, 7.4, 7.3]
+
+ name: ${{ matrix.os }} - P${{ matrix.php }}
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Cache dependencies
+ uses: actions/cache@v2
+ with:
+ path: ~/.composer/cache/files
+ key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ extensions: ldap, json
+ coverage: none
+
+ - name: Install dependencies
+ run: composer update --prefer-dist --no-interaction
+
+ - name: Execute tests
+ run: vendor/bin/phpunit
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.gitignore b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.gitignore
new file mode 100644
index 0000000..d5389fd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.gitignore
@@ -0,0 +1,5 @@
+vendor
+composer.lock
+.php_cs.cache
+.phpunit.result.cache
+.php-cs-fixer.cache
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.scrutinizer.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.scrutinizer.yml
new file mode 100644
index 0000000..b3f8f88
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.scrutinizer.yml
@@ -0,0 +1,9 @@
+filter:
+ excluded_paths:
+ - tests/*
+build:
+ nodes:
+ analysis:
+ tests:
+ override:
+ - command: php-scrutinizer-run
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.styleci.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.styleci.yml
new file mode 100644
index 0000000..c774021
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/.styleci.yml
@@ -0,0 +1,4 @@
+preset: laravel
+enabled:
+ - phpdoc_align
+ - unalign_double_arrow
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/composer.json
new file mode 100644
index 0000000..2e995d9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/composer.json
@@ -0,0 +1,59 @@
+{
+ "name": "directorytree/ldaprecord",
+ "type": "library",
+ "description": "A fully-featured LDAP ORM.",
+ "homepage": "https://www.ldaprecord.com",
+ "keywords": [
+ "active directory",
+ "directory",
+ "ad",
+ "ldap",
+ "windows",
+ "adldap",
+ "adldap2",
+ "ldaprecord",
+ "orm"
+ ],
+ "license": "MIT",
+ "support": {
+ "docs": "https://ldaprecord.com",
+ "issues": "https://github.com/DirectoryTree/LdapRecord/issues",
+ "source": "https://github.com/DirectoryTree/LdapRecord",
+ "email": "steven_bauman@outlook.com"
+ },
+ "authors": [
+ {
+ "name": "Steve Bauman",
+ "email": "steven_bauman@outlook.com",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "php": ">=7.3",
+ "ext-ldap": "*",
+ "ext-json": "*",
+ "psr/log": "^1.0",
+ "psr/simple-cache": "^1.0",
+ "nesbot/carbon": "^1.0|^2.0",
+ "tightenco/collect": "^5.6|^6.0|^7.0|^8.0",
+ "illuminate/contracts": "^5.0|^6.0|^7.0|^8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.0",
+ "mockery/mockery": "^1.0",
+ "spatie/ray": "^1.24"
+ },
+ "archive": {
+ "exclude": ["/tests"]
+ },
+ "autoload": {
+ "psr-4": {
+ "LdapRecord\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "LdapRecord\\Tests\\": "tests/"
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/license.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/license.md
new file mode 100644
index 0000000..c25dc60
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/license.md
@@ -0,0 +1,8 @@
+The MIT License (MIT)
+Copyright © Steve Bauman
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/phpunit.xml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/phpunit.xml
new file mode 100644
index 0000000..d03fdc2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/phpunit.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="false"
+ backupStaticAttributes="false"
+ bootstrap="vendor/autoload.php"
+ colors="true"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ processIsolation="false"
+ stopOnFailure="false"
+ >
+ <testsuites>
+ <testsuite name="LdapRecord Test Suite">
+ <directory suffix="Test.php">./tests/</directory>
+ </testsuite>
+ </testsuites>
+</phpunit>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/psalm.xml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/psalm.xml
new file mode 100644
index 0000000..7c0333d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/psalm.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<psalm
+ errorLevel="7"
+ resolveFromConfigFile="true"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="https://getpsalm.org/schema/config"
+ xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+>
+ <projectFiles>
+ <directory name="src" />
+ <ignoreFiles>
+ <directory name="vendor" />
+ </ignoreFiles>
+ </projectFiles>
+</psalm>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/readme.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/readme.md
new file mode 100644
index 0000000..08ecd9e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/readme.md
@@ -0,0 +1,94 @@
+<!-- readme.md -->
+
+<p align="center">
+ <img src="https://ldaprecord.com/logo.svg" width="400">
+</p>
+
+<p align="center">
+ <a href="https://github.com/DirectoryTree/LdapRecord/actions">
+ <img src="https://img.shields.io/github/workflow/status/directorytree/ldaprecord/run-tests.svg?style=flat-square">
+ </a>
+ <a href="https://scrutinizer-ci.com/g/DirectoryTree/LdapRecord/?branch=master">
+ <img src="https://img.shields.io/scrutinizer/g/DirectoryTree/LdapRecord/master.svg?style=flat-square"/>
+ </a>
+ <a href="https://packagist.org/packages/DirectoryTree/LdapRecord">
+ <img src="https://img.shields.io/packagist/dt/DirectoryTree/LdapRecord.svg?style=flat-square"/>
+ </a>
+ <a href="https://packagist.org/packages/DirectoryTree/LdapRecord">
+ <img src="https://img.shields.io/packagist/v/DirectoryTree/LdapRecord.svg?style=flat-square"/>
+ </a>
+ <a href="https://packagist.org/packages/DirectoryTree/LdapRecord">
+ <img src="https://img.shields.io/github/license/DirectoryTree/LdapRecord.svg?style=flat-square"/>
+ </a>
+</p>
+
+<p align="center">
+ Working with LDAP doesn't need to be hard.
+</p>
+
+<p align="center">
+ LdapRecord is a fully-featured <a href="https://en.wikipedia.org/wiki/Active_record_pattern">Active Record</a>
+ ORM that makes working with LDAP directories a breeze 🍃
+</p>
+
+<h4 align="center">
+ <a href="https://ldaprecord.com/docs/core/v2/quickstart/">Quickstart</a>
+ <span> · </span>
+ <a href="https://ldaprecord.com/docs/core/v2/">Documentation</a>
+ <span> · </span>
+ <a href="https://github.com/DirectoryTree/LdapRecord-Laravel">Laravel Integration</a>
+ <span> · </span>
+ <a href="https://github.com/DirectoryTree/LdapRecord/discussions/new">Post a Question</a>
+</h4>
+
+---
+
+⏲ **Up and Running Fast**
+
+Connect to your LDAP servers and start running queries at lightning speed.
+
+💡 **Fluent Filter Builder**
+
+Find the LDAP objects you're looking for with a fluent LDAP filter builder.
+
+💼 **Multi-Domain Ready**
+
+Built-in connection management allows you to access multiple domains without breaking a sweat.
+
+🔥 **Supercharged Active Record**
+
+Create and modify LDAP objects with minimal code.
+
+---
+
+<h3 align="center">
+Active Directory Features
+</h3>
+
+🚪 **Enable / Disable Accounts**
+
+Detect and assign User Account Control values on accounts with the fluent [Account Control builder](https://ldaprecord.com/docs/core/v2/active-directory/users/#uac).
+
+🔑 **Reset / Change Passwords**
+
+Built-in support for [changing](https://ldaprecord.com/docs/core/v2/active-directory/users/#changing-passwords) and [resetting](https://ldaprecord.com/docs/core/v2/active-directory/users/#resetting-passwords) passwords on Active Directory accounts.
+
+🗑 **Restore Deleted Objects**
+
+We've all been there -- accidentally deleting a user or group in Active Directory. [Restore them](https://ldaprecord.com/docs/core/v2/models/#restoring-deleted-models) by seamlessly accessing your directory's recycle bin.
+
+---
+
+<h3 align="center">LdapRecord is Supportware™</h3>
+
+<p align="center">If you require support using LdapRecord, a <a href="https://github.com/sponsors/stevebauman">sponsorship</a> is required :pray:</p>
+
+<p align="center">Thank you for your understanding :heart:</p>
+
+---
+
+<h3 align="center">Security Vulnerabilities</h3>
+
+<p align="center">If you discover a security vulnerability within LdapRecord, please send an e-mail to Steve Bauman via <a href="mailto:steven_bauman@outlook.com">steven_bauman@outlook.com</a>.</p>
+
+<p align="center">All security vulnerabilities will be promptly addressed.</p>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/BindException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/BindException.php
new file mode 100644
index 0000000..d87abc1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/BindException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace LdapRecord\Auth;
+
+use LdapRecord\LdapRecordException;
+
+class BindException extends LdapRecordException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Attempting.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Attempting.php
new file mode 100644
index 0000000..3776401
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Attempting.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Auth\Events;
+
+class Attempting extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Binding.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Binding.php
new file mode 100644
index 0000000..faffd85
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Binding.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Auth\Events;
+
+class Binding extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Bound.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Bound.php
new file mode 100644
index 0000000..65a3fae
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Bound.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Auth\Events;
+
+class Bound extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Event.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Event.php
new file mode 100644
index 0000000..83716b4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Event.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace LdapRecord\Auth\Events;
+
+use LdapRecord\LdapInterface;
+
+abstract class Event
+{
+ /**
+ * The connection that the username and password is being bound on.
+ *
+ * @var LdapInterface
+ */
+ protected $connection;
+
+ /**
+ * The username that is being used for binding.
+ *
+ * @var string
+ */
+ protected $username;
+
+ /**
+ * The password that is being used for binding.
+ *
+ * @var string
+ */
+ protected $password;
+
+ /**
+ * Constructor.
+ *
+ * @param LdapInterface $connection
+ * @param string $username
+ * @param string $password
+ */
+ public function __construct(LdapInterface $connection, $username, $password)
+ {
+ $this->connection = $connection;
+ $this->username = $username;
+ $this->password = $password;
+ }
+
+ /**
+ * Returns the events connection.
+ *
+ * @return LdapInterface
+ */
+ public function getConnection()
+ {
+ return $this->connection;
+ }
+
+ /**
+ * Returns the authentication events username.
+ *
+ * @return string
+ */
+ public function getUsername()
+ {
+ return $this->username;
+ }
+
+ /**
+ * Returns the authentication events password.
+ *
+ * @return string
+ */
+ public function getPassword()
+ {
+ return $this->password;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Failed.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Failed.php
new file mode 100644
index 0000000..7133e43
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Failed.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Auth\Events;
+
+class Failed extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Passed.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Passed.php
new file mode 100644
index 0000000..2442f3e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Events/Passed.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Auth\Events;
+
+class Passed extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Guard.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Guard.php
new file mode 100644
index 0000000..696cc40
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/Guard.php
@@ -0,0 +1,234 @@
+<?php
+
+namespace LdapRecord\Auth;
+
+use Exception;
+use LdapRecord\Auth\Events\Attempting;
+use LdapRecord\Auth\Events\Binding;
+use LdapRecord\Auth\Events\Bound;
+use LdapRecord\Auth\Events\Failed;
+use LdapRecord\Auth\Events\Passed;
+use LdapRecord\Configuration\DomainConfiguration;
+use LdapRecord\Events\DispatcherInterface;
+use LdapRecord\LdapInterface;
+
+class Guard
+{
+ /**
+ * The connection to bind to.
+ *
+ * @var LdapInterface
+ */
+ protected $connection;
+
+ /**
+ * The domain configuration to utilize.
+ *
+ * @var DomainConfiguration
+ */
+ protected $configuration;
+
+ /**
+ * The event dispatcher.
+ *
+ * @var DispatcherInterface
+ */
+ protected $events;
+
+ /**
+ * Constructor.
+ *
+ * @param LdapInterface $connection
+ * @param DomainConfiguration $configuration
+ */
+ public function __construct(LdapInterface $connection, DomainConfiguration $configuration)
+ {
+ $this->connection = $connection;
+ $this->configuration = $configuration;
+ }
+
+ /**
+ * Attempt binding a user to the LDAP server.
+ *
+ * @param string $username
+ * @param string $password
+ * @param bool $stayBound
+ *
+ * @throws UsernameRequiredException
+ * @throws PasswordRequiredException
+ *
+ * @return bool
+ */
+ public function attempt($username, $password, $stayBound = false)
+ {
+ switch (true) {
+ case empty($username):
+ throw new UsernameRequiredException('A username must be specified.');
+ case empty($password):
+ throw new PasswordRequiredException('A password must be specified.');
+ }
+
+ $this->fireAttemptingEvent($username, $password);
+
+ try {
+ $this->bind($username, $password);
+
+ $authenticated = true;
+
+ $this->firePassedEvent($username, $password);
+ } catch (BindException $e) {
+ $authenticated = false;
+ }
+
+ if (! $stayBound) {
+ $this->bindAsConfiguredUser();
+ }
+
+ return $authenticated;
+ }
+
+ /**
+ * Attempt binding a user to the LDAP server. Supports anonymous binding.
+ *
+ * @param string|null $username
+ * @param string|null $password
+ *
+ * @throws BindException
+ * @throws \LdapRecord\ConnectionException
+ */
+ public function bind($username = null, $password = null)
+ {
+ $this->fireBindingEvent($username, $password);
+
+ // Prior to binding, we will upgrade our connectivity to TLS on our current
+ // connection and ensure we are not already bound before upgrading.
+ // This is to prevent subsequent upgrading on several binds.
+ if ($this->connection->isUsingTLS() && ! $this->connection->isBound()) {
+ $this->connection->startTLS();
+ }
+
+ try {
+ if (! $this->connection->bind($username, $password)) {
+ throw new Exception($this->connection->getLastError(), $this->connection->errNo());
+ }
+
+ $this->fireBoundEvent($username, $password);
+ } catch (Exception $e) {
+ $this->fireFailedEvent($username, $password);
+
+ throw BindException::withDetailedError($e, $this->connection->getDetailedError());
+ }
+ }
+
+ /**
+ * Bind to the LDAP server using the configured username and password.
+ *
+ * @throws BindException
+ * @throws \LdapRecord\ConnectionException
+ * @throws \LdapRecord\Configuration\ConfigurationException
+ */
+ public function bindAsConfiguredUser()
+ {
+ $this->bind(
+ $this->configuration->get('username'),
+ $this->configuration->get('password')
+ );
+ }
+
+ /**
+ * Get the event dispatcher instance.
+ *
+ * @return DispatcherInterface
+ */
+ public function getDispatcher()
+ {
+ return $this->events;
+ }
+
+ /**
+ * Set the event dispatcher instance.
+ *
+ * @param DispatcherInterface $dispatcher
+ *
+ * @return void
+ */
+ public function setDispatcher(DispatcherInterface $dispatcher)
+ {
+ $this->events = $dispatcher;
+ }
+
+ /**
+ * Fire the attempting event.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @return void
+ */
+ protected function fireAttemptingEvent($username, $password)
+ {
+ if (isset($this->events)) {
+ $this->events->fire(new Attempting($this->connection, $username, $password));
+ }
+ }
+
+ /**
+ * Fire the passed event.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @return void
+ */
+ protected function firePassedEvent($username, $password)
+ {
+ if (isset($this->events)) {
+ $this->events->fire(new Passed($this->connection, $username, $password));
+ }
+ }
+
+ /**
+ * Fire the failed event.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @return void
+ */
+ protected function fireFailedEvent($username, $password)
+ {
+ if (isset($this->events)) {
+ $this->events->fire(new Failed($this->connection, $username, $password));
+ }
+ }
+
+ /**
+ * Fire the binding event.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @return void
+ */
+ protected function fireBindingEvent($username, $password)
+ {
+ if (isset($this->events)) {
+ $this->events->fire(new Binding($this->connection, $username, $password));
+ }
+ }
+
+ /**
+ * Fire the bound event.
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @return void
+ */
+ protected function fireBoundEvent($username, $password)
+ {
+ if (isset($this->events)) {
+ $this->events->fire(new Bound($this->connection, $username, $password));
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/PasswordRequiredException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/PasswordRequiredException.php
new file mode 100644
index 0000000..7b2bbd1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/PasswordRequiredException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace LdapRecord\Auth;
+
+use LdapRecord\LdapRecordException;
+
+class PasswordRequiredException extends LdapRecordException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/UsernameRequiredException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/UsernameRequiredException.php
new file mode 100644
index 0000000..838ae58
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Auth/UsernameRequiredException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace LdapRecord\Auth;
+
+use LdapRecord\LdapRecordException;
+
+class UsernameRequiredException extends LdapRecordException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/ConfigurationException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/ConfigurationException.php
new file mode 100644
index 0000000..6a93b12
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/ConfigurationException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace LdapRecord\Configuration;
+
+use LdapRecord\LdapRecordException;
+
+class ConfigurationException extends LdapRecordException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/DomainConfiguration.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/DomainConfiguration.php
new file mode 100644
index 0000000..1dcdd1a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/DomainConfiguration.php
@@ -0,0 +1,178 @@
+<?php
+
+namespace LdapRecord\Configuration;
+
+use LdapRecord\LdapInterface;
+
+class DomainConfiguration
+{
+ /**
+ * The extended configuration options.
+ *
+ * @var array
+ */
+ protected static $extended = [];
+
+ /**
+ * The configuration options array.
+ *
+ * The default values for each key indicate the type of value it requires.
+ *
+ * @var array
+ */
+ protected $options = [
+ // An array of LDAP hosts.
+ 'hosts' => [],
+
+ // The global LDAP operation timeout limit in seconds.
+ 'timeout' => 5,
+
+ // The LDAP version to utilize.
+ 'version' => 3,
+
+ // The port to use for connecting to your hosts.
+ 'port' => LdapInterface::PORT,
+
+ // The base distinguished name of your domain.
+ 'base_dn' => '',
+
+ // The username to use for binding.
+ 'username' => '',
+
+ // The password to use for binding.
+ 'password' => '',
+
+ // Whether or not to use SSL when connecting.
+ 'use_ssl' => false,
+
+ // Whether or not to use TLS when connecting.
+ 'use_tls' => false,
+
+ // Whether or not follow referrals is enabled when performing LDAP operations.
+ 'follow_referrals' => false,
+
+ // Custom LDAP options.
+ 'options' => [],
+ ];
+
+ /**
+ * Constructor.
+ *
+ * @param array $options
+ *
+ * @throws ConfigurationException When an option value given is an invalid type.
+ */
+ public function __construct(array $options = [])
+ {
+ $this->options = array_merge($this->options, static::$extended);
+
+ foreach ($options as $key => $value) {
+ $this->set($key, $value);
+ }
+ }
+
+ /**
+ * Extend the configuration with a custom option, or override an existing.
+ *
+ * @param string $option
+ * @param mixed $default
+ *
+ * @return void
+ */
+ public static function extend($option, $default = null)
+ {
+ static::$extended[$option] = $default;
+ }
+
+ /**
+ * Flush the extended configuration options.
+ *
+ * @return void
+ */
+ public static function flushExtended()
+ {
+ static::$extended = [];
+ }
+
+ /**
+ * Get all configuration options.
+ *
+ * @return array
+ */
+ public function all()
+ {
+ return $this->options;
+ }
+
+ /**
+ * Set a configuration option.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @throws ConfigurationException When an option value given is an invalid type.
+ */
+ public function set($key, $value)
+ {
+ if ($this->validate($key, $value)) {
+ $this->options[$key] = $value;
+ }
+ }
+
+ /**
+ * Returns the value for the specified configuration options.
+ *
+ * @param string $key
+ *
+ * @throws ConfigurationException When the option specified does not exist.
+ *
+ * @return mixed
+ */
+ public function get($key)
+ {
+ if (! $this->has($key)) {
+ throw new ConfigurationException("Option {$key} does not exist.");
+ }
+
+ return $this->options[$key];
+ }
+
+ /**
+ * Checks if a configuration option exists.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function has($key)
+ {
+ return array_key_exists($key, $this->options);
+ }
+
+ /**
+ * Validate the configuration option.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @throws ConfigurationException When an option value given is an invalid type.
+ *
+ * @return bool
+ */
+ protected function validate($key, $value)
+ {
+ $default = $this->get($key);
+
+ if (is_array($default)) {
+ $validator = new Validators\ArrayValidator($key, $value);
+ } elseif (is_int($default)) {
+ $validator = new Validators\IntegerValidator($key, $value);
+ } elseif (is_bool($default)) {
+ $validator = new Validators\BooleanValidator($key, $value);
+ } else {
+ $validator = new Validators\StringOrNullValidator($key, $value);
+ }
+
+ return $validator->validate();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/ArrayValidator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/ArrayValidator.php
new file mode 100644
index 0000000..4aa43ed
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/ArrayValidator.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace LdapRecord\Configuration\Validators;
+
+class ArrayValidator extends Validator
+{
+ /**
+ * The validation exception message.
+ *
+ * @var string
+ */
+ protected $message = 'Option [:option] must be an array.';
+
+ /**
+ * @inheritdoc
+ */
+ public function passes()
+ {
+ return is_array($this->value);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/BooleanValidator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/BooleanValidator.php
new file mode 100644
index 0000000..1d25a4b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/BooleanValidator.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace LdapRecord\Configuration\Validators;
+
+class BooleanValidator extends Validator
+{
+ /**
+ * The validation exception message.
+ *
+ * @var string
+ */
+ protected $message = 'Option [:option] must be a boolean.';
+
+ /**
+ * @inheritdoc
+ */
+ public function passes()
+ {
+ return is_bool($this->value);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/IntegerValidator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/IntegerValidator.php
new file mode 100644
index 0000000..5c4f0f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/IntegerValidator.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace LdapRecord\Configuration\Validators;
+
+class IntegerValidator extends Validator
+{
+ /**
+ * The validation exception message.
+ *
+ * @var string
+ */
+ protected $message = 'Option [:option] must be an integer.';
+
+ /**
+ * @inheritdoc
+ */
+ public function passes()
+ {
+ return is_numeric($this->value);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/StringOrNullValidator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/StringOrNullValidator.php
new file mode 100644
index 0000000..bc23372
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/StringOrNullValidator.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace LdapRecord\Configuration\Validators;
+
+class StringOrNullValidator extends Validator
+{
+ /**
+ * The validation exception message.
+ *
+ * @var string
+ */
+ protected $message = 'Option [:option] must be a string or null.';
+
+ /**
+ * @inheritdoc
+ */
+ public function passes()
+ {
+ return is_string($this->value) || is_null($this->value);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/Validator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/Validator.php
new file mode 100644
index 0000000..908a639
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/Validator.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace LdapRecord\Configuration\Validators;
+
+use LdapRecord\Configuration\ConfigurationException;
+
+abstract class Validator
+{
+ /**
+ * The configuration key under validation.
+ *
+ * @var string
+ */
+ protected $key;
+
+ /**
+ * The configuration value under validation.
+ *
+ * @var mixed
+ */
+ protected $value;
+
+ /**
+ * The validation exception message.
+ *
+ * @var string
+ */
+ protected $message;
+
+ /**
+ * Constructor.
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ public function __construct($key, $value)
+ {
+ $this->key = $key;
+ $this->value = $value;
+ }
+
+ /**
+ * Determine if the validation rule passes.
+ *
+ * @return bool
+ */
+ abstract public function passes();
+
+ /**
+ * Validate the configuration value.
+ *
+ * @throws ConfigurationException
+ *
+ * @return bool
+ */
+ public function validate()
+ {
+ if (! $this->passes()) {
+ $this->fail();
+ }
+
+ return true;
+ }
+
+ /**
+ * Throw a configuration exception.
+ *
+ * @throws ConfigurationException
+ *
+ * @return void
+ */
+ protected function fail()
+ {
+ throw new ConfigurationException(
+ str_replace(':option', $this->key, $this->message)
+ );
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Connection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Connection.php
new file mode 100644
index 0000000..8ba0ef1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Connection.php
@@ -0,0 +1,511 @@
+<?php
+
+namespace LdapRecord;
+
+use Carbon\Carbon;
+use Closure;
+use LdapRecord\Auth\Guard;
+use LdapRecord\Configuration\DomainConfiguration;
+use LdapRecord\Events\DispatcherInterface;
+use LdapRecord\Query\Builder;
+use LdapRecord\Query\Cache;
+use Psr\SimpleCache\CacheInterface;
+
+class Connection
+{
+ use DetectsErrors;
+
+ /**
+ * The underlying LDAP connection.
+ *
+ * @var Ldap
+ */
+ protected $ldap;
+
+ /**
+ * The cache driver.
+ *
+ * @var Cache|null
+ */
+ protected $cache;
+
+ /**
+ * The domain configuration.
+ *
+ * @var DomainConfiguration
+ */
+ protected $configuration;
+
+ /**
+ * The event dispatcher;.
+ *
+ * @var DispatcherInterface|null
+ */
+ protected $dispatcher;
+
+ /**
+ * The current host connected to.
+ *
+ * @var string
+ */
+ protected $host;
+
+ /**
+ * The configured domain hosts.
+ *
+ * @var array
+ */
+ protected $hosts = [];
+
+ /**
+ * The attempted hosts that failed connecting to.
+ *
+ * @var array
+ */
+ protected $attempted = [];
+
+ /**
+ * The callback to execute upon total connection failure.
+ *
+ * @var Closure
+ */
+ protected $failed;
+
+ /**
+ * The authentication guard resolver.
+ *
+ * @var Closure
+ */
+ protected $authGuardResolver;
+
+ /**
+ * Whether the connection is retrying the initial connection attempt.
+ *
+ * @var bool
+ */
+ protected $retryingInitialConnection = false;
+
+ /**
+ * Constructor.
+ *
+ * @param array $config
+ * @param LdapInterface|null $ldap
+ */
+ public function __construct($config = [], LdapInterface $ldap = null)
+ {
+ $this->setConfiguration($config);
+
+ $this->setLdapConnection($ldap ?? new Ldap());
+
+ $this->failed = function () {
+ $this->dispatch(new Events\ConnectionFailed($this));
+ };
+
+ $this->authGuardResolver = function () {
+ return new Guard($this->ldap, $this->configuration);
+ };
+ }
+
+ /**
+ * Set the connection configuration.
+ *
+ * @param array $config
+ *
+ * @throws Configuration\ConfigurationException
+ *
+ * @return $this
+ */
+ public function setConfiguration($config = [])
+ {
+ $this->configuration = new DomainConfiguration($config);
+
+ $this->hosts = $this->configuration->get('hosts');
+
+ $this->host = reset($this->hosts);
+
+ return $this;
+ }
+
+ /**
+ * Set the LDAP connection.
+ *
+ * @param LdapInterface $ldap
+ *
+ * @return $this
+ */
+ public function setLdapConnection(LdapInterface $ldap)
+ {
+ $this->ldap = $ldap;
+
+ return $this;
+ }
+
+ /**
+ * Set the event dispatcher.
+ *
+ * @param DispatcherInterface $dispatcher
+ *
+ * @return $this
+ */
+ public function setDispatcher(DispatcherInterface $dispatcher)
+ {
+ $this->dispatcher = $dispatcher;
+
+ return $this;
+ }
+
+ /**
+ * Initializes the LDAP connection.
+ *
+ * @return void
+ */
+ public function initialize()
+ {
+ $this->configure();
+
+ $this->ldap->connect($this->host, $this->configuration->get('port'));
+ }
+
+ /**
+ * Configure the LDAP connection.
+ *
+ * @return void
+ */
+ protected function configure()
+ {
+ if ($this->configuration->get('use_ssl')) {
+ $this->ldap->ssl();
+ } elseif ($this->configuration->get('use_tls')) {
+ $this->ldap->tls();
+ }
+
+ $this->ldap->setOptions(array_replace(
+ $this->configuration->get('options'),
+ [
+ LDAP_OPT_PROTOCOL_VERSION => $this->configuration->get('version'),
+ LDAP_OPT_NETWORK_TIMEOUT => $this->configuration->get('timeout'),
+ LDAP_OPT_REFERRALS => $this->configuration->get('follow_referrals'),
+ ]
+ ));
+ }
+
+ /**
+ * Set the cache store.
+ *
+ * @param CacheInterface $store
+ *
+ * @return $this
+ */
+ public function setCache(CacheInterface $store)
+ {
+ $this->cache = new Cache($store);
+
+ return $this;
+ }
+
+ /**
+ * Get the cache store.
+ *
+ * @return Cache|null
+ */
+ public function getCache()
+ {
+ return $this->cache;
+ }
+
+ /**
+ * Get the LDAP configuration instance.
+ *
+ * @return DomainConfiguration
+ */
+ public function getConfiguration()
+ {
+ return $this->configuration;
+ }
+
+ /**
+ * Get the LDAP connection instance.
+ *
+ * @return Ldap
+ */
+ public function getLdapConnection()
+ {
+ return $this->ldap;
+ }
+
+ /**
+ * Bind to the LDAP server.
+ *
+ * If no username or password is specified, then the configured credentials are used.
+ *
+ * @param string|null $username
+ * @param string|null $password
+ *
+ * @throws Auth\BindException
+ * @throws LdapRecordException
+ *
+ * @return Connection
+ */
+ public function connect($username = null, $password = null)
+ {
+ $attempt = function () use ($username, $password) {
+ $this->dispatch(new Events\Connecting($this));
+
+ is_null($username) && is_null($password)
+ ? $this->auth()->bindAsConfiguredUser()
+ : $this->auth()->bind($username, $password);
+
+ $this->dispatch(new Events\Connected($this));
+
+ $this->retryingInitialConnection = false;
+ };
+
+ try {
+ $this->runOperationCallback($attempt);
+ } catch (LdapRecordException $e) {
+ $this->retryingInitialConnection = true;
+
+ $this->retryOnNextHost($e, $attempt);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Reconnect to the LDAP server.
+ *
+ * @throws Auth\BindException
+ * @throws ConnectionException
+ *
+ * @return void
+ */
+ public function reconnect()
+ {
+ $this->reinitialize();
+
+ $this->connect();
+ }
+
+ /**
+ * Reinitialize the connection.
+ *
+ * @return void
+ */
+ protected function reinitialize()
+ {
+ $this->disconnect();
+
+ $this->initialize();
+ }
+
+ /**
+ * Disconnect from the LDAP server.
+ *
+ * @return void
+ */
+ public function disconnect()
+ {
+ $this->ldap->close();
+ }
+
+ /**
+ * Dispatch an event.
+ *
+ * @param object $event
+ *
+ * @return void
+ */
+ public function dispatch($event)
+ {
+ if (isset($this->dispatcher)) {
+ $this->dispatcher->dispatch($event);
+ }
+ }
+
+ /**
+ * Get the attempted hosts that failed connecting to.
+ *
+ * @return array
+ */
+ public function attempted()
+ {
+ return $this->attempted;
+ }
+
+ /**
+ * Perform the operation on the LDAP connection.
+ *
+ * @param Closure $operation
+ *
+ * @return mixed
+ */
+ public function run(Closure $operation)
+ {
+ try {
+ // Before running the operation, we will check if the current
+ // connection is bound and connect if necessary. Otherwise
+ // some LDAP operations will not be executed properly.
+ if (! $this->isConnected()) {
+ $this->connect();
+ }
+
+ return $this->runOperationCallback($operation);
+ } catch (LdapRecordException $e) {
+ if ($exception = $this->getExceptionForCauseOfFailure($e)) {
+ throw $exception;
+ }
+
+ return $this->tryAgainIfCausedByLostConnection($e, $operation);
+ }
+ }
+
+ /**
+ * Attempt to get an exception for the cause of failure.
+ *
+ * @param LdapRecordException $e
+ *
+ * @return mixed
+ */
+ protected function getExceptionForCauseOfFailure(LdapRecordException $e)
+ {
+ switch (true) {
+ case $this->errorContainsMessage($e->getMessage(), 'Already exists'):
+ return Exceptions\AlreadyExistsException::withDetailedError($e, $e->getDetailedError());
+ case $this->errorContainsMessage($e->getMessage(), 'Insufficient access'):
+ return Exceptions\InsufficientAccessException::withDetailedError($e, $e->getDetailedError());
+ case $this->errorContainsMessage($e->getMessage(), 'Constraint violation'):
+ return Exceptions\ConstraintViolationException::withDetailedError($e, $e->getDetailedError());
+ default:
+ return;
+ }
+ }
+
+ /**
+ * Run the operation callback on the current LDAP connection.
+ *
+ * @param Closure $operation
+ *
+ * @throws LdapRecordException
+ *
+ * @return mixed
+ */
+ protected function runOperationCallback(Closure $operation)
+ {
+ return $operation($this->ldap);
+ }
+
+ /**
+ * Get a new auth guard instance.
+ *
+ * @return Auth\Guard
+ */
+ public function auth()
+ {
+ if (! $this->ldap->isConnected()) {
+ $this->initialize();
+ }
+
+ $guard = call_user_func($this->authGuardResolver);
+
+ $guard->setDispatcher(
+ Container::getInstance()->getEventDispatcher()
+ );
+
+ return $guard;
+ }
+
+ /**
+ * Get a new query builder for the connection.
+ *
+ * @return Query\Builder
+ */
+ public function query()
+ {
+ return (new Builder($this))
+ ->setCache($this->cache)
+ ->setBaseDn($this->configuration->get('base_dn'));
+ }
+
+ /**
+ * Determine if the LDAP connection is bound.
+ *
+ * @return bool
+ */
+ public function isConnected()
+ {
+ return $this->ldap->isBound();
+ }
+
+ /**
+ * Attempt to retry an LDAP operation if due to a lost connection.
+ *
+ * @param LdapRecordException $e
+ * @param Closure $operation
+ *
+ * @throws LdapRecordException
+ *
+ * @return mixed
+ */
+ protected function tryAgainIfCausedByLostConnection(LdapRecordException $e, Closure $operation)
+ {
+ // If the operation failed due to a lost or failed connection,
+ // we'll attempt reconnecting and running the operation again
+ // underneath the same host, and then move onto the next.
+ if ($this->causedByLostConnection($e->getMessage())) {
+ return $this->retry($operation);
+ }
+
+ throw $e;
+ }
+
+ /**
+ * Retry the operation on the current host.
+ *
+ * @param Closure $operation
+ *
+ * @throws LdapRecordException
+ *
+ * @return mixed
+ */
+ protected function retry(Closure $operation)
+ {
+ try {
+ $this->retryingInitialConnection
+ ? $this->reinitialize()
+ : $this->reconnect();
+
+ return $this->runOperationCallback($operation);
+ } catch (LdapRecordException $e) {
+ return $this->retryOnNextHost($e, $operation);
+ }
+ }
+
+ /**
+ * Attempt the operation again on the next host.
+ *
+ * @param LdapRecordException $e
+ * @param Closure $operation
+ *
+ * @throws LdapRecordException
+ *
+ * @return mixed
+ */
+ protected function retryOnNextHost(LdapRecordException $e, Closure $operation)
+ {
+ $this->attempted[$this->host] = Carbon::now();
+
+ if (($key = array_search($this->host, $this->hosts)) !== false) {
+ unset($this->hosts[$key]);
+ }
+
+ if ($next = reset($this->hosts)) {
+ $this->host = $next;
+
+ return $this->tryAgainIfCausedByLostConnection($e, $operation);
+ }
+
+ call_user_func($this->failed, $this->ldap);
+
+ throw $e;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ConnectionException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ConnectionException.php
new file mode 100644
index 0000000..81691bb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ConnectionException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord;
+
+class ConnectionException extends LdapRecordException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ConnectionManager.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ConnectionManager.php
new file mode 100644
index 0000000..0eacbc3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ConnectionManager.php
@@ -0,0 +1,320 @@
+<?php
+
+namespace LdapRecord;
+
+use BadMethodCallException;
+use LdapRecord\Events\Dispatcher;
+use LdapRecord\Events\DispatcherInterface;
+use LdapRecord\Events\Logger;
+use Psr\Log\LoggerInterface;
+
+class ConnectionManager
+{
+ /**
+ * The logger instance.
+ *
+ * @var LoggerInterface|null
+ */
+ protected $logger;
+
+ /**
+ * The event dispatcher instance.
+ *
+ * @var DispatcherInterface|null
+ */
+ protected $dispatcher;
+
+ /**
+ * The added LDAP connections.
+ *
+ * @var Connection[]
+ */
+ protected $connections = [];
+
+ /**
+ * The name of the default connection.
+ *
+ * @var string
+ */
+ protected $default = 'default';
+
+ /**
+ * The events to register listeners for during initialization.
+ *
+ * @var array
+ */
+ protected $listen = [
+ 'LdapRecord\Auth\Events\*',
+ 'LdapRecord\Query\Events\*',
+ 'LdapRecord\Models\Events\*',
+ ];
+
+ /**
+ * The method calls to proxy for compatibility.
+ *
+ * To be removed in the next major version.
+ *
+ * @var array
+ */
+ protected $proxy = [
+ 'reset' => 'flush',
+ 'addConnection' => 'add',
+ 'getConnection' => 'get',
+ 'allConnections' => 'all',
+ 'removeConnection' => 'remove',
+ 'getDefaultConnection' => 'getDefault',
+ 'setDefaultConnection' => 'setDefault',
+ 'getEventDispatcher' => 'dispatcher',
+ 'setEventDispatcher' => 'setDispatcher',
+ ];
+
+ /**
+ * Constructor.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->dispatcher = new Dispatcher();
+ }
+
+ /**
+ * Forward missing method calls onto the instance.
+ *
+ * @param string $method
+ * @param mixed $args
+ *
+ * @return mixed
+ */
+ public function __call($method, $args)
+ {
+ $method = $this->proxy[$method] ?? $method;
+
+ if (! method_exists($this, $method)) {
+ throw new BadMethodCallException(sprintf(
+ 'Call to undefined method %s::%s()',
+ static::class,
+ $method
+ ));
+ }
+
+ return $this->{$method}(...$args);
+ }
+
+ /**
+ * Add a new connection.
+ *
+ * @param Connection $connection
+ * @param string|null $name
+ *
+ * @return $this
+ */
+ public function add(Connection $connection, $name = null)
+ {
+ $this->connections[$name ?? $this->default] = $connection;
+
+ if ($this->dispatcher) {
+ $connection->setDispatcher($this->dispatcher);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Remove a connection.
+ *
+ * @param $name
+ *
+ * @return $this
+ */
+ public function remove($name)
+ {
+ unset($this->connections[$name]);
+
+ return $this;
+ }
+
+ /**
+ * Get all of the connections.
+ *
+ * @return Connection[]
+ */
+ public function all()
+ {
+ return $this->connections;
+ }
+
+ /**
+ * Get a connection by name or return the default.
+ *
+ * @param string|null $name
+ *
+ * @throws ContainerException If the given connection does not exist.
+ *
+ * @return Connection
+ */
+ public function get($name = null)
+ {
+ if ($this->exists($name = $name ?? $this->default)) {
+ return $this->connections[$name];
+ }
+
+ throw new ContainerException("The LDAP connection [$name] does not exist.");
+ }
+
+ /**
+ * Return the default connection.
+ *
+ * @return Connection
+ */
+ public function getDefault()
+ {
+ return $this->get($this->default);
+ }
+
+ /**
+ * Get the default connection name.
+ *
+ * @return string
+ */
+ public function getDefaultConnectionName()
+ {
+ return $this->default;
+ }
+
+ /**
+ * Checks if the connection exists.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function exists($name)
+ {
+ return array_key_exists($name, $this->connections);
+ }
+
+ /**
+ * Set the default connection name.
+ *
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function setDefault($name = null)
+ {
+ $this->default = $name;
+
+ return $this;
+ }
+
+ /**
+ * Flush the manager of all instances and connections.
+ *
+ * @return $this
+ */
+ public function flush()
+ {
+ $this->logger = null;
+
+ $this->connections = [];
+
+ $this->dispatcher = new Dispatcher();
+
+ return $this;
+ }
+
+ /**
+ * Get the logger instance.
+ *
+ * @return LoggerInterface|null
+ */
+ public function getLogger()
+ {
+ return $this->logger;
+ }
+
+ /**
+ * Set the event logger to use.
+ *
+ * @param LoggerInterface $logger
+ *
+ * @return void
+ */
+ public function setLogger(LoggerInterface $logger)
+ {
+ $this->logger = $logger;
+
+ $this->initEventLogger();
+ }
+
+ /**
+ * Initialize the event logger.
+ *
+ * @return void
+ */
+ public function initEventLogger()
+ {
+ $logger = $this->newEventLogger();
+
+ foreach ($this->listen as $event) {
+ $this->dispatcher->listen($event, function ($eventName, $events) use ($logger) {
+ foreach ($events as $event) {
+ $logger->log($event);
+ }
+ });
+ }
+ }
+
+ /**
+ * Make a new event logger instance.
+ *
+ * @return Logger
+ */
+ protected function newEventLogger()
+ {
+ return new Logger($this->logger);
+ }
+
+ /**
+ * Unset the logger instance.
+ *
+ * @return void
+ */
+ public function unsetLogger()
+ {
+ $this->logger = null;
+ }
+
+ /**
+ * Get the event dispatcher.
+ *
+ * @return DispatcherInterface|null
+ */
+ public function dispatcher()
+ {
+ return $this->dispatcher;
+ }
+
+ /**
+ * Set the event dispatcher.
+ *
+ * @param DispatcherInterface $dispatcher
+ *
+ * @return void
+ */
+ public function setDispatcher(DispatcherInterface $dispatcher)
+ {
+ $this->dispatcher = $dispatcher;
+ }
+
+ /**
+ * Unset the event dispatcher.
+ *
+ * @return void
+ */
+ public function unsetEventDispatcher()
+ {
+ $this->dispatcher = null;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Container.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Container.php
new file mode 100644
index 0000000..f458951
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Container.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace LdapRecord;
+
+/**
+ * @method static $this reset()
+ * @method static Connection[] all()
+ * @method static Connection[] allConnections()
+ * @method static Connection getDefaultConnection()
+ * @method static Connection get(string|null $name = null)
+ * @method static Connection getConnection(string|null $name = null)
+ * @method static bool exists(string $name)
+ * @method static $this remove(string|null $name = null)
+ * @method static $this removeConnection(string|null $name = null)
+ * @method static $this setDefault(string|null $name = null)
+ * @method static $this setDefaultConnection(string|null $name = null)
+ * @method static $this add(Connection $connection, string|null $name = null)
+ * @method static $this addConnection(Connection $connection, string|null $name = null)
+ */
+class Container
+{
+ /**
+ * The current container instance.
+ *
+ * @var Container
+ */
+ protected static $instance;
+
+ /**
+ * The connection manager instance.
+ *
+ * @var ConnectionManager
+ */
+ protected $manager;
+
+ /**
+ * The methods to passthru, for compatibility.
+ *
+ * @var array
+ */
+ protected $passthru = [
+ 'reset', 'flush',
+ 'add', 'addConnection',
+ 'remove', 'removeConnection',
+ 'setDefault', 'setDefaultConnection',
+ ];
+
+ /**
+ * Forward missing static calls onto the current instance.
+ *
+ * @param string $method
+ * @param mixed $args
+ *
+ * @return mixed
+ */
+ public static function __callStatic($method, $args)
+ {
+ return static::getInstance()->{$method}(...$args);
+ }
+
+ /**
+ * Get or set the current instance of the container.
+ *
+ * @return Container
+ */
+ public static function getInstance()
+ {
+ return static::$instance ?? static::getNewInstance();
+ }
+
+ /**
+ * Set the container instance.
+ *
+ * @param Container|null $container
+ *
+ * @return Container|null
+ */
+ public static function setInstance(self $container = null)
+ {
+ return static::$instance = $container;
+ }
+
+ /**
+ * Set and get a new instance of the container.
+ *
+ * @return Container
+ */
+ public static function getNewInstance()
+ {
+ return static::setInstance(new static());
+ }
+
+ /**
+ * Constructor.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->manager = new ConnectionManager();
+ }
+
+ /**
+ * Forward missing method calls onto the connection manager.
+ *
+ * @param string $method
+ * @param mixed $args
+ *
+ * @return mixed
+ */
+ public function __call($method, $args)
+ {
+ $value = $this->manager->{$method}(...$args);
+
+ return in_array($method, $this->passthru) ? $this : $value;
+ }
+
+ /**
+ * Get the connection manager.
+ *
+ * @return ConnectionManager
+ */
+ public function manager()
+ {
+ return $this->manager;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ContainerException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ContainerException.php
new file mode 100644
index 0000000..0ab29cf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ContainerException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord;
+
+class ContainerException extends LdapRecordException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/DetailedError.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/DetailedError.php
new file mode 100644
index 0000000..d61159e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/DetailedError.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace LdapRecord;
+
+class DetailedError
+{
+ /**
+ * The error code from ldap_errno.
+ *
+ * @var int|null
+ */
+ protected $errorCode;
+
+ /**
+ * The error message from ldap_error.
+ *
+ * @var string|null
+ */
+ protected $errorMessage;
+
+ /**
+ * The diagnostic message when retrieved after an ldap_error.
+ *
+ * @var string|null
+ */
+ protected $diagnosticMessage;
+
+ /**
+ * Constructor.
+ *
+ * @param int $errorCode
+ * @param string $errorMessage
+ * @param string $diagnosticMessage
+ */
+ public function __construct($errorCode, $errorMessage, $diagnosticMessage)
+ {
+ $this->errorCode = $errorCode;
+ $this->errorMessage = $errorMessage;
+ $this->diagnosticMessage = $diagnosticMessage;
+ }
+
+ /**
+ * Returns the LDAP error code.
+ *
+ * @return int
+ */
+ public function getErrorCode()
+ {
+ return $this->errorCode;
+ }
+
+ /**
+ * Returns the LDAP error message.
+ *
+ * @return string
+ */
+ public function getErrorMessage()
+ {
+ return $this->errorMessage;
+ }
+
+ /**
+ * Returns the LDAP diagnostic message.
+ *
+ * @return string
+ */
+ public function getDiagnosticMessage()
+ {
+ return $this->diagnosticMessage;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/DetectsErrors.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/DetectsErrors.php
new file mode 100644
index 0000000..e8997a9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/DetectsErrors.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace LdapRecord;
+
+trait DetectsErrors
+{
+ /**
+ * Determine if the error was caused by a lost connection.
+ *
+ * @param string $error
+ *
+ * @return bool
+ */
+ protected function causedByLostConnection($error)
+ {
+ return $this->errorContainsMessage($error, ["Can't contact LDAP server", 'Operations error']);
+ }
+
+ /**
+ * Determine if the error was caused by lack of pagination support.
+ *
+ * @param string $error
+ *
+ * @return bool
+ */
+ protected function causedByPaginationSupport($error)
+ {
+ return $this->errorContainsMessage($error, 'No server controls in result');
+ }
+
+ /**
+ * Determine if the error was caused by a size limit warning.
+ *
+ * @param $error
+ *
+ * @return bool
+ */
+ protected function causedBySizeLimit($error)
+ {
+ return $this->errorContainsMessage($error, ['Partial search results returned', 'Size limit exceeded']);
+ }
+
+ /**
+ * Determine if the error was caused by a "No such object" warning.
+ *
+ * @param string $error
+ *
+ * @return bool
+ */
+ protected function causedByNoSuchObject($error)
+ {
+ return $this->errorContainsMessage($error, ['No such object']);
+ }
+
+ /**
+ * Determine if the error contains the any of the messages.
+ *
+ * @param string $error
+ * @param string|array $messages
+ *
+ * @return bool
+ */
+ protected function errorContainsMessage($error, $messages = [])
+ {
+ foreach ((array) $messages as $message) {
+ if (strpos($error, $message) !== false) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/EscapesValues.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/EscapesValues.php
new file mode 100644
index 0000000..acfc020
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/EscapesValues.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace LdapRecord;
+
+use LdapRecord\Models\Attributes\EscapedValue;
+
+trait EscapesValues
+{
+ /**
+ * Prepare a value to be escaped.
+ *
+ * @param string $value
+ * @param string $ignore
+ * @param int $flags
+ *
+ * @return EscapedValue
+ */
+ public function escape($value, $ignore = '', $flags = 0)
+ {
+ return new EscapedValue($value, $ignore, $flags);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Connected.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Connected.php
new file mode 100644
index 0000000..d9505da
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Connected.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Events;
+
+class Connected extends ConnectionEvent
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Connecting.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Connecting.php
new file mode 100644
index 0000000..d2922ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Connecting.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Events;
+
+class Connecting extends ConnectionEvent
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/ConnectionEvent.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/ConnectionEvent.php
new file mode 100644
index 0000000..e9c2c35
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/ConnectionEvent.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace LdapRecord\Events;
+
+use LdapRecord\Connection;
+
+abstract class ConnectionEvent
+{
+ /**
+ * The LDAP connection.
+ *
+ * @var Connection
+ */
+ protected $connection;
+
+ /**
+ * Constructor.
+ *
+ * @param Connection $connection
+ */
+ public function __construct(Connection $connection)
+ {
+ $this->connection = $connection;
+ }
+
+ /**
+ * Get the connection pertaining to the event.
+ *
+ * @return Connection
+ */
+ public function getConnection()
+ {
+ return $this->connection;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/ConnectionFailed.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/ConnectionFailed.php
new file mode 100644
index 0000000..7e110c1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/ConnectionFailed.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Events;
+
+class ConnectionFailed extends ConnectionEvent
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Dispatcher.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Dispatcher.php
new file mode 100644
index 0000000..a4ae3de
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Dispatcher.php
@@ -0,0 +1,334 @@
+<?php
+
+namespace LdapRecord\Events;
+
+use LdapRecord\Support\Arr;
+
+/**
+ * Class Dispatcher.
+ *
+ * Handles event listening and dispatching.
+ *
+ * This code was taken out of the Laravel Framework core
+ * with broadcasting and queuing omitted to remove
+ * an extra dependency that would be required.
+ *
+ * @author Taylor Otwell
+ *
+ * @see https://github.com/laravel/framework
+ */
+class Dispatcher implements DispatcherInterface
+{
+ /**
+ * The registered event listeners.
+ *
+ * @var array
+ */
+ protected $listeners = [];
+
+ /**
+ * The wildcard listeners.
+ *
+ * @var array
+ */
+ protected $wildcards = [];
+
+ /**
+ * The cached wildcard listeners.
+ *
+ * @var array
+ */
+ protected $wildcardsCache = [];
+
+ /**
+ * @inheritdoc
+ */
+ public function listen($events, $listener)
+ {
+ foreach ((array) $events as $event) {
+ if (strpos($event, '*') !== false) {
+ $this->setupWildcardListen($event, $listener);
+ } else {
+ $this->listeners[$event][] = $this->makeListener($listener);
+ }
+ }
+ }
+
+ /**
+ * Setup a wildcard listener callback.
+ *
+ * @param string $event
+ * @param mixed $listener
+ *
+ * @return void
+ */
+ protected function setupWildcardListen($event, $listener)
+ {
+ $this->wildcards[$event][] = $this->makeListener($listener, true);
+
+ $this->wildcardsCache = [];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hasListeners($eventName)
+ {
+ return isset($this->listeners[$eventName]) || isset($this->wildcards[$eventName]);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function until($event, $payload = [])
+ {
+ return $this->dispatch($event, $payload, true);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function fire($event, $payload = [], $halt = false)
+ {
+ return $this->dispatch($event, $payload, $halt);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function dispatch($event, $payload = [], $halt = false)
+ {
+ // When the given "event" is actually an object we will assume it is an event
+ // object and use the class as the event name and this event itself as the
+ // payload to the handler, which makes object based events quite simple.
+ [$event, $payload] = $this->parseEventAndPayload(
+ $event,
+ $payload
+ );
+
+ $responses = [];
+
+ foreach ($this->getListeners($event) as $listener) {
+ $response = $listener($event, $payload);
+
+ // If a response is returned from the listener and event halting is enabled
+ // we will just return this response, and not call the rest of the event
+ // listeners. Otherwise we will add the response on the response list.
+ if ($halt && ! is_null($response)) {
+ return $response;
+ }
+
+ // If a boolean false is returned from a listener, we will stop propagating
+ // the event to any further listeners down in the chain, else we keep on
+ // looping through the listeners and firing every one in our sequence.
+ if ($response === false) {
+ break;
+ }
+
+ $responses[] = $response;
+ }
+
+ return $halt ? null : $responses;
+ }
+
+ /**
+ * Parse the given event and payload and prepare them for dispatching.
+ *
+ * @param mixed $event
+ * @param mixed $payload
+ *
+ * @return array
+ */
+ protected function parseEventAndPayload($event, $payload)
+ {
+ if (is_object($event)) {
+ [$payload, $event] = [[$event], get_class($event)];
+ }
+
+ return [$event, Arr::wrap($payload)];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getListeners($eventName)
+ {
+ $listeners = $this->listeners[$eventName] ?? [];
+
+ $listeners = array_merge(
+ $listeners,
+ $this->wildcardsCache[$eventName] ?? $this->getWildcardListeners($eventName)
+ );
+
+ return class_exists($eventName, false)
+ ? $this->addInterfaceListeners($eventName, $listeners)
+ : $listeners;
+ }
+
+ /**
+ * Get the wildcard listeners for the event.
+ *
+ * @param string $eventName
+ *
+ * @return array
+ */
+ protected function getWildcardListeners($eventName)
+ {
+ $wildcards = [];
+
+ foreach ($this->wildcards as $key => $listeners) {
+ if ($this->wildcardContainsEvent($key, $eventName)) {
+ $wildcards = array_merge($wildcards, $listeners);
+ }
+ }
+
+ return $this->wildcardsCache[$eventName] = $wildcards;
+ }
+
+ /**
+ * Determine if the wildcard matches or contains the given event.
+ *
+ * This function is a direct excerpt from Laravel's Str::is().
+ *
+ * @param string $wildcard
+ * @param string $eventName
+ *
+ * @return bool
+ */
+ protected function wildcardContainsEvent($wildcard, $eventName)
+ {
+ $patterns = Arr::wrap($wildcard);
+
+ if (empty($patterns)) {
+ return false;
+ }
+
+ foreach ($patterns as $pattern) {
+ // If the given event is an exact match we can of course return true right
+ // from the beginning. Otherwise, we will translate asterisks and do an
+ // actual pattern match against the two strings to see if they match.
+ if ($pattern == $eventName) {
+ return true;
+ }
+
+ $pattern = preg_quote($pattern, '#');
+
+ // Asterisks are translated into zero-or-more regular expression wildcards
+ // to make it convenient to check if the strings starts with the given
+ // pattern such as "library/*", making any string check convenient.
+ $pattern = str_replace('\*', '.*', $pattern);
+
+ if (preg_match('#^'.$pattern.'\z#u', $eventName) === 1) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Add the listeners for the event's interfaces to the given array.
+ *
+ * @param string $eventName
+ * @param array $listeners
+ *
+ * @return array
+ */
+ protected function addInterfaceListeners($eventName, array $listeners = [])
+ {
+ foreach (class_implements($eventName) as $interface) {
+ if (isset($this->listeners[$interface])) {
+ foreach ($this->listeners[$interface] as $names) {
+ $listeners = array_merge($listeners, (array) $names);
+ }
+ }
+ }
+
+ return $listeners;
+ }
+
+ /**
+ * Register an event listener with the dispatcher.
+ *
+ * @param \Closure|string $listener
+ * @param bool $wildcard
+ *
+ * @return \Closure
+ */
+ public function makeListener($listener, $wildcard = false)
+ {
+ if (is_string($listener)) {
+ return $this->createClassListener($listener, $wildcard);
+ }
+
+ return function ($event, $payload) use ($listener, $wildcard) {
+ if ($wildcard) {
+ return $listener($event, $payload);
+ }
+
+ return $listener(...array_values($payload));
+ };
+ }
+
+ /**
+ * Create a class based listener.
+ *
+ * @param string $listener
+ * @param bool $wildcard
+ *
+ * @return \Closure
+ */
+ protected function createClassListener($listener, $wildcard = false)
+ {
+ return function ($event, $payload) use ($listener, $wildcard) {
+ if ($wildcard) {
+ return call_user_func($this->createClassCallable($listener), $event, $payload);
+ }
+
+ return call_user_func_array(
+ $this->createClassCallable($listener),
+ $payload
+ );
+ };
+ }
+
+ /**
+ * Create the class based event callable.
+ *
+ * @param string $listener
+ *
+ * @return callable
+ */
+ protected function createClassCallable($listener)
+ {
+ [$class, $method] = $this->parseListenerCallback($listener);
+
+ return [new $class(), $method];
+ }
+
+ /**
+ * Parse the class listener into class and method.
+ *
+ * @param string $listener
+ *
+ * @return array
+ */
+ protected function parseListenerCallback($listener)
+ {
+ return strpos($listener, '@') !== false
+ ? explode('@', $listener, 2)
+ : [$listener, 'handle'];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function forget($event)
+ {
+ if (strpos($event, '*') !== false) {
+ unset($this->wildcards[$event]);
+ } else {
+ unset($this->listeners[$event]);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/DispatcherInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/DispatcherInterface.php
new file mode 100644
index 0000000..6b7cb10
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/DispatcherInterface.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace LdapRecord\Events;
+
+interface DispatcherInterface
+{
+ /**
+ * Register an event listener with the dispatcher.
+ *
+ * @param string|array $events
+ * @param mixed $listener
+ *
+ * @return void
+ */
+ public function listen($events, $listener);
+
+ /**
+ * Determine if a given event has listeners.
+ *
+ * @param string $eventName
+ *
+ * @return bool
+ */
+ public function hasListeners($eventName);
+
+ /**
+ * Fire an event until the first non-null response is returned.
+ *
+ * @param string|object $event
+ * @param mixed $payload
+ *
+ * @return array|null
+ */
+ public function until($event, $payload = []);
+
+ /**
+ * Fire an event and call the listeners.
+ *
+ * @param string|object $event
+ * @param mixed $payload
+ * @param bool $halt
+ *
+ * @return mixed
+ */
+ public function fire($event, $payload = [], $halt = false);
+
+ /**
+ * Fire an event and call the listeners.
+ *
+ * @param string|object $event
+ * @param mixed $payload
+ * @param bool $halt
+ *
+ * @return array|null
+ */
+ public function dispatch($event, $payload = [], $halt = false);
+
+ /**
+ * Get all of the listeners for a given event name.
+ *
+ * @param string $eventName
+ *
+ * @return array
+ */
+ public function getListeners($eventName);
+
+ /**
+ * Remove a set of listeners from the dispatcher.
+ *
+ * @param string $event
+ *
+ * @return void
+ */
+ public function forget($event);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Logger.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Logger.php
new file mode 100644
index 0000000..f3840c2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Logger.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace LdapRecord\Events;
+
+use LdapRecord\Auth\Events\Event as AuthEvent;
+use LdapRecord\Auth\Events\Failed;
+use LdapRecord\Models\Events\Event as ModelEvent;
+use LdapRecord\Query\Events\QueryExecuted as QueryEvent;
+use Psr\Log\LoggerInterface;
+use ReflectionClass;
+
+class Logger
+{
+ /**
+ * The logger instance.
+ *
+ * @var LoggerInterface|null
+ */
+ protected $logger;
+
+ /**
+ * Constructor.
+ *
+ * @param LoggerInterface|null $logger
+ */
+ public function __construct(LoggerInterface $logger = null)
+ {
+ $this->logger = $logger;
+ }
+
+ /**
+ * Logs the given event.
+ *
+ * @param mixed $event
+ *
+ * @return void
+ */
+ public function log($event)
+ {
+ switch (true) {
+ case $event instanceof AuthEvent:
+ return $this->auth($event);
+ case $event instanceof ModelEvent:
+ return $this->model($event);
+ case $event instanceof QueryEvent:
+ return $this->query($event);
+ }
+ }
+
+ /**
+ * Logs an authentication event.
+ *
+ * @param AuthEvent $event
+ *
+ * @return void
+ */
+ public function auth(AuthEvent $event)
+ {
+ if (isset($this->logger)) {
+ $connection = $event->getConnection();
+
+ $message = "LDAP ({$connection->getHost()})"
+ ." - Operation: {$this->getOperationName($event)}"
+ ." - Username: {$event->getUsername()}";
+
+ $result = null;
+ $type = 'info';
+
+ if (is_a($event, Failed::class)) {
+ $type = 'warning';
+ $result = " - Reason: {$connection->getLastError()}";
+ }
+
+ $this->logger->$type($message.$result);
+ }
+ }
+
+ /**
+ * Logs a model event.
+ *
+ * @param ModelEvent $event
+ *
+ * @return void
+ */
+ public function model(ModelEvent $event)
+ {
+ if (isset($this->logger)) {
+ $model = $event->getModel();
+
+ $on = get_class($model);
+
+ $connection = $model->getConnection()->getLdapConnection();
+
+ $message = "LDAP ({$connection->getHost()})"
+ ." - Operation: {$this->getOperationName($event)}"
+ ." - On: {$on}"
+ ." - Distinguished Name: {$model->getDn()}";
+
+ $this->logger->info($message);
+ }
+ }
+
+ /**
+ * Logs a query event.
+ *
+ * @param QueryEvent $event
+ *
+ * @return void
+ */
+ public function query(QueryEvent $event)
+ {
+ if (isset($this->logger)) {
+ $query = $event->getQuery();
+
+ $connection = $query->getConnection()->getLdapConnection();
+
+ $selected = implode(',', $query->getSelects());
+
+ $message = "LDAP ({$connection->getHost()})"
+ ." - Operation: {$this->getOperationName($event)}"
+ ." - Base DN: {$query->getBaseDn()}"
+ ." - Filter: {$query->getQuery()}"
+ ." - Selected: ({$selected})"
+ ." - Time Elapsed: {$event->getTime()}";
+
+ $this->logger->info($message);
+ }
+ }
+
+ /**
+ * Returns the operational name of the given event.
+ *
+ * @param mixed $event
+ *
+ * @return string
+ */
+ protected function getOperationName($event)
+ {
+ return (new ReflectionClass($event))->getShortName();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Exceptions/AlreadyExistsException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Exceptions/AlreadyExistsException.php
new file mode 100644
index 0000000..2298caf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Exceptions/AlreadyExistsException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace LdapRecord\Exceptions;
+
+use LdapRecord\LdapRecordException;
+
+class AlreadyExistsException extends LdapRecordException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Exceptions/ConstraintViolationException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Exceptions/ConstraintViolationException.php
new file mode 100644
index 0000000..641843a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Exceptions/ConstraintViolationException.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace LdapRecord\Exceptions;
+
+use LdapRecord\DetectsErrors;
+use LdapRecord\LdapRecordException;
+
+class ConstraintViolationException extends LdapRecordException
+{
+ use DetectsErrors;
+
+ /**
+ * Determine if the exception was generated due to the password policy.
+ *
+ * @return bool
+ */
+ public function causedByPasswordPolicy()
+ {
+ return isset($this->detailedError)
+ ? $this->errorContainsMessage($this->detailedError->getDiagnosticMessage(), '0000052D')
+ : false;
+ }
+
+ /**
+ * Determine if the exception was generated due to an incorrect password.
+ *
+ * @return bool
+ */
+ public function causedByIncorrectPassword()
+ {
+ return isset($this->detailedError)
+ ? $this->errorContainsMessage($this->detailedError->getDiagnosticMessage(), '00000056')
+ : false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Exceptions/InsufficientAccessException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Exceptions/InsufficientAccessException.php
new file mode 100644
index 0000000..89c55fd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Exceptions/InsufficientAccessException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace LdapRecord\Exceptions;
+
+use LdapRecord\LdapRecordException;
+
+class InsufficientAccessException extends LdapRecordException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/HandlesConnection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/HandlesConnection.php
new file mode 100644
index 0000000..41334b6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/HandlesConnection.php
@@ -0,0 +1,261 @@
+<?php
+
+namespace LdapRecord;
+
+use Closure;
+use ErrorException;
+use Exception;
+
+trait HandlesConnection
+{
+ /**
+ * The LDAP host that is currently connected.
+ *
+ * @var string|null
+ */
+ protected $host;
+
+ /**
+ * The LDAP connection resource.
+ *
+ * @var resource|null
+ */
+ protected $connection;
+
+ /**
+ * The bound status of the connection.
+ *
+ * @var bool
+ */
+ protected $bound = false;
+
+ /**
+ * Whether the connection must be bound over SSL.
+ *
+ * @var bool
+ */
+ protected $useSSL = false;
+
+ /**
+ * Whether the connection must be bound over TLS.
+ *
+ * @var bool
+ */
+ protected $useTLS = false;
+
+ /**
+ * @inheritdoc
+ */
+ public function isUsingSSL()
+ {
+ return $this->useSSL;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function isUsingTLS()
+ {
+ return $this->useTLS;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function isBound()
+ {
+ return $this->bound;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function isConnected()
+ {
+ return ! is_null($this->connection);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function canChangePasswords()
+ {
+ return $this->isUsingSSL() || $this->isUsingTLS();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function ssl($enabled = true)
+ {
+ $this->useSSL = $enabled;
+
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function tls($enabled = true)
+ {
+ $this->useTLS = $enabled;
+
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setOptions(array $options = [])
+ {
+ foreach ($options as $option => $value) {
+ $this->setOption($option, $value);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getHost()
+ {
+ return $this->host;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getConnection()
+ {
+ return $this->connection;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getProtocol()
+ {
+ return $this->isUsingSSL() ? LdapInterface::PROTOCOL_SSL : LdapInterface::PROTOCOL;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getExtendedError()
+ {
+ return $this->getDiagnosticMessage();
+ }
+
+ /**
+ * Convert warnings to exceptions for the given operation.
+ *
+ * @param Closure $operation
+ *
+ * @throws LdapRecordException
+ *
+ * @return mixed
+ */
+ protected function executeFailableOperation(Closure $operation)
+ {
+ // If some older versions of PHP, errors are reported instead of throwing
+ // exceptions, which could be a signifcant detriment to our application.
+ // Here, we will enforce these operations to throw exceptions instead.
+ set_error_handler(function ($severity, $message, $file, $line) {
+ if (! $this->shouldBypassError($message)) {
+ throw new ErrorException($message, $severity, $severity, $file, $line);
+ }
+ });
+
+ try {
+ if (($result = $operation()) !== false) {
+ return $result;
+ }
+
+ // If the failed query operation was a based on a query being executed
+ // -- such as a search, read, or listing, then we can safely return
+ // the failed response here and prevent throwning an exception.
+ if ($this->shouldBypassFailure($method = debug_backtrace()[1]['function'])) {
+ return $result;
+ }
+
+ throw new Exception("LDAP operation [$method] failed.");
+ } catch (ErrorException $e) {
+ throw LdapRecordException::withDetailedError($e, $this->getDetailedError());
+ } finally {
+ restore_error_handler();
+ }
+ }
+
+ /**
+ * Determine if the failed operation should be bypassed.
+ *
+ * @param string $method
+ *
+ * @return bool
+ */
+ protected function shouldBypassFailure($method)
+ {
+ return in_array($method, ['search', 'read', 'listing']);
+ }
+
+ /**
+ * Determine if the error should be bypassed.
+ *
+ * @param string $error
+ *
+ * @return bool
+ */
+ protected function shouldBypassError($error)
+ {
+ return $this->causedByPaginationSupport($error) || $this->causedBySizeLimit($error) || $this->causedByNoSuchObject($error);
+ }
+
+ /**
+ * Determine if the current PHP version supports server controls.
+ *
+ * @deprecated since v2.5.0
+ *
+ * @return bool
+ */
+ public function supportsServerControlsInMethods()
+ {
+ return version_compare(PHP_VERSION, '7.3.0') >= 0;
+ }
+
+ /**
+ * Generates an LDAP connection string for each host given.
+ *
+ * @param string|array $hosts
+ * @param string $port
+ *
+ * @return string
+ */
+ protected function makeConnectionUris($hosts, $port)
+ {
+ // If an attempt to connect via SSL protocol is being performed,
+ // and we are still using the default port, we will swap it
+ // for the default SSL port, for developer convenience.
+ if ($this->isUsingSSL() && $port == LdapInterface::PORT) {
+ $port = LdapInterface::PORT_SSL;
+ }
+
+ // The blank space here is intentional. PHP's LDAP extension
+ // requires additional hosts to be seperated by a blank
+ // space, so that it can parse each individually.
+ return implode(' ', $this->assembleHostUris($hosts, $port));
+ }
+
+ /**
+ * Assemble the host URI strings.
+ *
+ * @param array|string $hosts
+ * @param string $port
+ *
+ * @return array
+ */
+ protected function assembleHostUris($hosts, $port)
+ {
+ return array_map(function ($host) use ($port) {
+ return "{$this->getProtocol()}{$host}:{$port}";
+ }, (array) $hosts);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Ldap.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Ldap.php
new file mode 100644
index 0000000..6503cea
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Ldap.php
@@ -0,0 +1,480 @@
+<?php
+
+namespace LdapRecord;
+
+class Ldap implements LdapInterface
+{
+ use HandlesConnection, DetectsErrors;
+
+ /**
+ * @inheritdoc
+ */
+ public function getEntries($searchResults)
+ {
+ return $this->executeFailableOperation(function () use ($searchResults) {
+ return ldap_get_entries($this->connection, $searchResults);
+ });
+ }
+
+ /**
+ * Retrieves the first entry from a search result.
+ *
+ * @see http://php.net/manual/en/function.ldap-first-entry.php
+ *
+ * @param resource $searchResults
+ *
+ * @return resource
+ */
+ public function getFirstEntry($searchResults)
+ {
+ return $this->executeFailableOperation(function () use ($searchResults) {
+ return ldap_first_entry($this->connection, $searchResults);
+ });
+ }
+
+ /**
+ * Retrieves the next entry from a search result.
+ *
+ * @see http://php.net/manual/en/function.ldap-next-entry.php
+ *
+ * @param resource $entry
+ *
+ * @return resource
+ */
+ public function getNextEntry($entry)
+ {
+ return $this->executeFailableOperation(function () use ($entry) {
+ return ldap_next_entry($this->connection, $entry);
+ });
+ }
+
+ /**
+ * Retrieves the ldap entry's attributes.
+ *
+ * @see http://php.net/manual/en/function.ldap-get-attributes.php
+ *
+ * @param resource $entry
+ *
+ * @return array|false
+ */
+ public function getAttributes($entry)
+ {
+ return $this->executeFailableOperation(function () use ($entry) {
+ return ldap_get_attributes($this->connection, $entry);
+ });
+ }
+
+ /**
+ * Returns the number of entries from a search result.
+ *
+ * @see http://php.net/manual/en/function.ldap-count-entries.php
+ *
+ * @param resource $searchResults
+ *
+ * @return int
+ */
+ public function countEntries($searchResults)
+ {
+ return $this->executeFailableOperation(function () use ($searchResults) {
+ return ldap_count_entries($this->connection, $searchResults);
+ });
+ }
+
+ /**
+ * Compare value of attribute found in entry specified with DN.
+ *
+ * @see http://php.net/manual/en/function.ldap-compare.php
+ *
+ * @param string $dn
+ * @param string $attribute
+ * @param string $value
+ *
+ * @return mixed
+ */
+ public function compare($dn, $attribute, $value)
+ {
+ return $this->executeFailableOperation(function () use ($dn, $attribute, $value) {
+ return ldap_compare($this->connection, $dn, $attribute, $value);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getLastError()
+ {
+ if (! $this->connection) {
+ return;
+ }
+
+ return ldap_error($this->connection);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getDetailedError()
+ {
+ if (! $number = $this->errNo()) {
+ return;
+ }
+
+ $this->getOption(LDAP_OPT_DIAGNOSTIC_MESSAGE, $message);
+
+ return new DetailedError($number, $this->err2Str($number), $message);
+ }
+
+ /**
+ * Get all binary values from the specified result entry.
+ *
+ * @see http://php.net/manual/en/function.ldap-get-values-len.php
+ *
+ * @param $entry
+ * @param $attribute
+ *
+ * @return array
+ */
+ public function getValuesLen($entry, $attribute)
+ {
+ return $this->executeFailableOperation(function () use ($entry, $attribute) {
+ return ldap_get_values_len($this->connection, $entry, $attribute);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setOption($option, $value)
+ {
+ return ldap_set_option($this->connection, $option, $value);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getOption($option, &$value = null)
+ {
+ ldap_get_option($this->connection, $option, $value);
+
+ return $value;
+ }
+
+ /**
+ * Set a callback function to do re-binds on referral chasing.
+ *
+ * @see http://php.net/manual/en/function.ldap-set-rebind-proc.php
+ *
+ * @param callable $callback
+ *
+ * @return bool
+ */
+ public function setRebindCallback(callable $callback)
+ {
+ return ldap_set_rebind_proc($this->connection, $callback);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function startTLS()
+ {
+ return $this->executeFailableOperation(function () {
+ return ldap_start_tls($this->connection);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function connect($hosts = [], $port = 389)
+ {
+ $this->bound = false;
+
+ $this->host = $this->makeConnectionUris($hosts, $port);
+
+ return $this->connection = $this->executeFailableOperation(function () {
+ return ldap_connect($this->host);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function close()
+ {
+ $result = is_resource($this->connection) ? @ldap_close($this->connection) : false;
+
+ $this->connection = null;
+ $this->bound = false;
+ $this->host = null;
+
+ return $result;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function search($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = null, $serverControls = [])
+ {
+ return $this->executeFailableOperation(function () use (
+ $dn,
+ $filter,
+ $fields,
+ $onlyAttributes,
+ $size,
+ $time,
+ $deref,
+ $serverControls
+ ) {
+ return empty($serverControls)
+ ? ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref)
+ : ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function listing($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = null, $serverControls = [])
+ {
+ return $this->executeFailableOperation(function () use (
+ $dn,
+ $filter,
+ $fields,
+ $onlyAttributes,
+ $size,
+ $time,
+ $deref,
+ $serverControls
+ ) {
+ return empty($serverControls)
+ ? ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref)
+ : ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function read($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = null, $serverControls = [])
+ {
+ return $this->executeFailableOperation(function () use (
+ $dn,
+ $filter,
+ $fields,
+ $onlyAttributes,
+ $size,
+ $time,
+ $deref,
+ $serverControls
+ ) {
+ return empty($serverControls)
+ ? ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref)
+ : ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function parseResult($result, &$errorCode, &$dn, &$errorMessage, &$referrals, &$serverControls = [])
+ {
+ return $this->executeFailableOperation(function () use (
+ $result,
+ &$errorCode,
+ &$dn,
+ &$errorMessage,
+ &$referrals,
+ &$serverControls
+ ) {
+ return empty($serverControls)
+ ? ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals)
+ : ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals, $serverControls);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function bind($username, $password)
+ {
+ return $this->bound = $this->executeFailableOperation(function () use ($username, $password) {
+ return ldap_bind($this->connection, $username, html_entity_decode($password));
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function add($dn, array $entry)
+ {
+ return $this->executeFailableOperation(function () use ($dn, $entry) {
+ return ldap_add($this->connection, $dn, $entry);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function delete($dn)
+ {
+ return $this->executeFailableOperation(function () use ($dn) {
+ return ldap_delete($this->connection, $dn);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function rename($dn, $newRdn, $newParent, $deleteOldRdn = false)
+ {
+ return $this->executeFailableOperation(function () use (
+ $dn,
+ $newRdn,
+ $newParent,
+ $deleteOldRdn
+ ) {
+ return ldap_rename($this->connection, $dn, $newRdn, $newParent, $deleteOldRdn);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function modify($dn, array $entry)
+ {
+ return $this->executeFailableOperation(function () use ($dn, $entry) {
+ return ldap_modify($this->connection, $dn, $entry);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function modifyBatch($dn, array $values)
+ {
+ return $this->executeFailableOperation(function () use ($dn, $values) {
+ return ldap_modify_batch($this->connection, $dn, $values);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function modAdd($dn, array $entry)
+ {
+ return $this->executeFailableOperation(function () use ($dn, $entry) {
+ return ldap_mod_add($this->connection, $dn, $entry);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function modReplace($dn, array $entry)
+ {
+ return $this->executeFailableOperation(function () use ($dn, $entry) {
+ return ldap_mod_replace($this->connection, $dn, $entry);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function modDelete($dn, array $entry)
+ {
+ return $this->executeFailableOperation(function () use ($dn, $entry) {
+ return ldap_mod_del($this->connection, $dn, $entry);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function controlPagedResult($pageSize = 1000, $isCritical = false, $cookie = '')
+ {
+ return $this->executeFailableOperation(function () use ($pageSize, $isCritical, $cookie) {
+ return ldap_control_paged_result($this->connection, $pageSize, $isCritical, $cookie);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function controlPagedResultResponse($result, &$cookie, &$estimated = null)
+ {
+ return $this->executeFailableOperation(function () use ($result, &$cookie, &$estimated) {
+ return ldap_control_paged_result_response($this->connection, $result, $cookie, $estimated);
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function freeResult($result)
+ {
+ return ldap_free_result($result);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function errNo()
+ {
+ return $this->connection ? ldap_errno($this->connection) : null;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function err2Str($number)
+ {
+ return ldap_err2str($number);
+ }
+
+ /**
+ * Returns the extended error hex code of the last command.
+ *
+ * @return string|null
+ */
+ public function getExtendedErrorHex()
+ {
+ if (preg_match("/(?<=data\s).*?(?=,)/", $this->getExtendedError(), $code)) {
+ return $code[0];
+ }
+ }
+
+ /**
+ * Returns the extended error code of the last command.
+ *
+ * @return bool|string
+ */
+ public function getExtendedErrorCode()
+ {
+ return $this->extractDiagnosticCode($this->getExtendedError());
+ }
+
+ /**
+ * Extract the diagnostic code from the message.
+ *
+ * @param string $message
+ *
+ * @return string|bool
+ */
+ public function extractDiagnosticCode($message)
+ {
+ preg_match('/^([\da-fA-F]+):/', $message, $matches);
+
+ return isset($matches[1]) ? $matches[1] : false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getDiagnosticMessage()
+ {
+ $this->getOption(LDAP_OPT_ERROR_STRING, $message);
+
+ return $message;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapInterface.php
new file mode 100644
index 0000000..a1773ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapInterface.php
@@ -0,0 +1,517 @@
+<?php
+
+namespace LdapRecord;
+
+interface LdapInterface
+{
+ /**
+ * The SSL LDAP protocol string.
+ *
+ * @var string
+ */
+ const PROTOCOL_SSL = 'ldaps://';
+
+ /**
+ * The standard LDAP protocol string.
+ *
+ * @var string
+ */
+ const PROTOCOL = 'ldap://';
+
+ /**
+ * The LDAP SSL port number.
+ *
+ * @var string
+ */
+ const PORT_SSL = 636;
+
+ /**
+ * The standard LDAP port number.
+ *
+ * @var string
+ */
+ const PORT = 389;
+
+ /**
+ * Various useful server control OID's.
+ *
+ * @see https://ldap.com/ldap-oid-reference-guide/
+ * @see http://msdn.microsoft.com/en-us/library/cc223359.aspx
+ */
+ const OID_SERVER_START_TLS = '1.3.6.1.4.1.1466.20037';
+ const OID_SERVER_PAGED_RESULTS = '1.2.840.113556.1.4.319';
+ const OID_SERVER_SHOW_DELETED = '1.2.840.113556.1.4.417';
+ const OID_SERVER_SORT = '1.2.840.113556.1.4.473';
+ const OID_SERVER_CROSSDOM_MOVE_TARGET = '1.2.840.113556.1.4.521';
+ const OID_SERVER_NOTIFICATION = '1.2.840.113556.1.4.528';
+ const OID_SERVER_EXTENDED_DN = '1.2.840.113556.1.4.529';
+ const OID_SERVER_LAZY_COMMIT = '1.2.840.113556.1.4.619';
+ const OID_SERVER_SD_FLAGS = '1.2.840.113556.1.4.801';
+ const OID_SERVER_TREE_DELETE = '1.2.840.113556.1.4.805';
+ const OID_SERVER_DIRSYNC = '1.2.840.113556.1.4.841';
+ const OID_SERVER_VERIFY_NAME = '1.2.840.113556.1.4.1338';
+ const OID_SERVER_DOMAIN_SCOPE = '1.2.840.113556.1.4.1339';
+ const OID_SERVER_SEARCH_OPTIONS = '1.2.840.113556.1.4.1340';
+ const OID_SERVER_PERMISSIVE_MODIFY = '1.2.840.113556.1.4.1413';
+ const OID_SERVER_ASQ = '1.2.840.113556.1.4.1504';
+ const OID_SERVER_FAST_BIND = '1.2.840.113556.1.4.1781';
+ const OID_SERVER_CONTROL_VLVREQUEST = '2.16.840.1.113730.3.4.9';
+
+ /**
+ * Query OID's.
+ *
+ * @see https://ldapwiki.com/wiki/LDAP_MATCHING_RULE_IN_CHAIN
+ */
+ const OID_MATCHING_RULE_IN_CHAIN = '1.2.840.113556.1.4.1941';
+
+ /**
+ * Set the current connection to use SSL.
+ *
+ * @param bool $enabled
+ *
+ * @return $this
+ */
+ public function ssl();
+
+ /**
+ * Determine if the current connection instance is using SSL.
+ *
+ * @return bool
+ */
+ public function isUsingSSL();
+
+ /**
+ * Set the current connection to use TLS.
+ *
+ * @param bool $enabled
+ *
+ * @return $this
+ */
+ public function tls();
+
+ /**
+ * Determine if the current connection instance is using TLS.
+ *
+ * @return bool
+ */
+ public function isUsingTLS();
+
+ /**
+ * Determine if the connection is bound.
+ *
+ * @return bool
+ */
+ public function isBound();
+
+ /**
+ * Determine if the connection has been created.
+ *
+ * @return bool
+ */
+ public function isConnected();
+
+ /**
+ * Determine the connection is able to modify passwords.
+ *
+ * @return bool
+ */
+ public function canChangePasswords();
+
+ /**
+ * Returns the full LDAP host URL.
+ *
+ * Ex: ldap://192.168.1.1:386
+ *
+ * @return string|null
+ */
+ public function getHost();
+
+ /**
+ * Get the underlying connection resource.
+ *
+ * @return resource|null
+ */
+ public function getConnection();
+
+ /**
+ * Retrieve the entries from a search result.
+ *
+ * @see http://php.net/manual/en/function.ldap-get-entries.php
+ *
+ * @param resource $searchResults
+ *
+ * @return array
+ */
+ public function getEntries($searchResults);
+
+ /**
+ * Retrieve the last error on the current connection.
+ *
+ * @see http://php.net/manual/en/function.ldap-error.php
+ *
+ * @return string|null
+ */
+ public function getLastError();
+
+ /**
+ * Return detailed information about an error.
+ *
+ * Returns false when there was a successful last request.
+ *
+ * Returns DetailedError when there was an error.
+ *
+ * @return DetailedError|null
+ */
+ public function getDetailedError();
+
+ /**
+ * Set an option on the current connection.
+ *
+ * @see http://php.net/manual/en/function.ldap-set-option.php
+ *
+ * @param int $option
+ * @param mixed $value
+ *
+ * @return bool
+ */
+ public function setOption($option, $value);
+
+ /**
+ * Set options on the current connection.
+ *
+ * @param array $options
+ *
+ * @return void
+ */
+ public function setOptions(array $options = []);
+
+ /**
+ * Get the value for the LDAP option.
+ *
+ * @see https://www.php.net/manual/en/function.ldap-get-option.php
+ *
+ * @param int $option
+ * @param mixed $value
+ *
+ * @return mixed
+ */
+ public function getOption($option, &$value = null);
+
+ /**
+ * Starts a connection using TLS.
+ *
+ * @see http://php.net/manual/en/function.ldap-start-tls.php
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function startTLS();
+
+ /**
+ * Connects to the specified hostname using the specified port.
+ *
+ * @see http://php.net/manual/en/function.ldap-start-tls.php
+ *
+ * @param string|array $hosts
+ * @param int $port
+ *
+ * @return resource|false
+ */
+ public function connect($hosts = [], $port = 389);
+
+ /**
+ * Closes the current connection.
+ *
+ * Returns false if no connection is present.
+ *
+ * @see http://php.net/manual/en/function.ldap-close.php
+ *
+ * @return bool
+ */
+ public function close();
+
+ /**
+ * Performs a search on the current connection.
+ *
+ * @see http://php.net/manual/en/function.ldap-search.php
+ *
+ * @param string $dn
+ * @param string $filter
+ * @param array $fields
+ * @param bool $onlyAttributes
+ * @param int $size
+ * @param int $time
+ * @param int $deref
+ * @param array $serverControls
+ *
+ * @return resource
+ */
+ public function search($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = null, $serverControls = []);
+
+ /**
+ * Performs a single level search on the current connection.
+ *
+ * @see http://php.net/manual/en/function.ldap-list.php
+ *
+ * @param string $dn
+ * @param string $filter
+ * @param array $fields
+ * @param bool $onlyAttributes
+ * @param int $size
+ * @param int $time
+ * @param int $deref
+ * @param array $serverControls
+ *
+ * @return resource
+ */
+ public function listing($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = null, $serverControls = []);
+
+ /**
+ * Reads an entry on the current connection.
+ *
+ * @see http://php.net/manual/en/function.ldap-read.php
+ *
+ * @param string $dn
+ * @param string $filter
+ * @param array $fields
+ * @param bool $onlyAttributes
+ * @param int $size
+ * @param int $time
+ * @param int $deref
+ * @param array $serverControls
+ *
+ * @return resource
+ */
+ public function read($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = null, $serverControls = []);
+
+ /**
+ * Extract information from an LDAP result.
+ *
+ * @see https://www.php.net/manual/en/function.ldap-parse-result.php
+ *
+ * @param resource $result
+ * @param int $errorCode
+ * @param string $dn
+ * @param string $errorMessage
+ * @param array $referrals
+ * @param array $serverControls
+ *
+ * @return bool
+ */
+ public function parseResult($result, &$errorCode, &$dn, &$errorMessage, &$referrals, &$serverControls = []);
+
+ /**
+ * Binds to the current connection using the specified username and password.
+ * If sasl is true, the current connection is bound using SASL.
+ *
+ * @see http://php.net/manual/en/function.ldap-bind.php
+ *
+ * @param string $username
+ * @param string $password
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function bind($username, $password);
+
+ /**
+ * Adds an entry to the current connection.
+ *
+ * @see http://php.net/manual/en/function.ldap-add.php
+ *
+ * @param string $dn
+ * @param array $entry
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function add($dn, array $entry);
+
+ /**
+ * Deletes an entry on the current connection.
+ *
+ * @see http://php.net/manual/en/function.ldap-delete.php
+ *
+ * @param string $dn
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function delete($dn);
+
+ /**
+ * Modify the name of an entry on the current connection.
+ *
+ * @see http://php.net/manual/en/function.ldap-rename.php
+ *
+ * @param string $dn
+ * @param string $newRdn
+ * @param string $newParent
+ * @param bool $deleteOldRdn
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function rename($dn, $newRdn, $newParent, $deleteOldRdn = false);
+
+ /**
+ * Modifies an existing entry on the current connection.
+ *
+ * @see http://php.net/manual/en/function.ldap-modify.php
+ *
+ * @param string $dn
+ * @param array $entry
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function modify($dn, array $entry);
+
+ /**
+ * Batch modifies an existing entry on the current connection.
+ *
+ * @see http://php.net/manual/en/function.ldap-modify-batch.php
+ *
+ * @param string $dn
+ * @param array $values
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function modifyBatch($dn, array $values);
+
+ /**
+ * Add attribute values to current attributes.
+ *
+ * @see http://php.net/manual/en/function.ldap-mod-add.php
+ *
+ * @param string $dn
+ * @param array $entry
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function modAdd($dn, array $entry);
+
+ /**
+ * Replaces attribute values with new ones.
+ *
+ * @see http://php.net/manual/en/function.ldap-mod-replace.php
+ *
+ * @param string $dn
+ * @param array $entry
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function modReplace($dn, array $entry);
+
+ /**
+ * Delete attribute values from current attributes.
+ *
+ * @see http://php.net/manual/en/function.ldap-mod-del.php
+ *
+ * @param string $dn
+ * @param array $entry
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function modDelete($dn, array $entry);
+
+ /**
+ * Send LDAP pagination control.
+ *
+ * @see http://php.net/manual/en/function.ldap-control-paged-result.php
+ *
+ * @param int $pageSize
+ * @param bool $isCritical
+ * @param string $cookie
+ *
+ * @return bool
+ */
+ public function controlPagedResult($pageSize = 1000, $isCritical = false, $cookie = '');
+
+ /**
+ * Retrieve the LDAP pagination cookie.
+ *
+ * @see http://php.net/manual/en/function.ldap-control-paged-result-response.php
+ *
+ * @param resource $result
+ * @param string $cookie
+ *
+ * @return bool
+ */
+ public function controlPagedResultResponse($result, &$cookie);
+
+ /**
+ * Frees up the memory allocated internally to store the result.
+ *
+ * @see https://www.php.net/manual/en/function.ldap-free-result.php
+ *
+ * @param resource $result
+ *
+ * @return bool
+ */
+ public function freeResult($result);
+
+ /**
+ * Returns the error number of the last command executed.
+ *
+ * @see http://php.net/manual/en/function.ldap-errno.php
+ *
+ * @return int|null
+ */
+ public function errNo();
+
+ /**
+ * Returns the error string of the specified error number.
+ *
+ * @see http://php.net/manual/en/function.ldap-err2str.php
+ *
+ * @param int $number
+ *
+ * @return string
+ */
+ public function err2Str($number);
+
+ /**
+ * Returns the LDAP protocol to utilize for the current connection.
+ *
+ * @return string
+ */
+ public function getProtocol();
+
+ /**
+ * Returns the extended error code of the last command.
+ *
+ * @return string
+ */
+ public function getExtendedError();
+
+ /**
+ * Return the diagnostic Message.
+ *
+ * @return string
+ */
+ public function getDiagnosticMessage();
+
+ /**
+ * Determine if the current PHP version supports server controls.
+ *
+ * @deprecated since v2.5.0
+ *
+ * @return bool
+ */
+ public function supportsServerControlsInMethods();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapRecordException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapRecordException.php
new file mode 100644
index 0000000..b2439bf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapRecordException.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace LdapRecord;
+
+use Exception;
+
+class LdapRecordException extends Exception
+{
+ /**
+ * The detailed LDAP error (if available).
+ *
+ * @var DetailedError|null
+ */
+ protected $detailedError;
+
+ /**
+ * Create a new Bind Exception with a detailed connection error.
+ *
+ * @param Exception $e
+ * @param DetailedError|null $error
+ *
+ * @return $this
+ */
+ public static function withDetailedError(Exception $e, DetailedError $error = null)
+ {
+ return (new static($e->getMessage(), $e->getCode(), $e))->setDetailedError($error);
+ }
+
+ /**
+ * Set the detailed error.
+ *
+ * @param DetailedError|null $error
+ *
+ * @return $this
+ */
+ public function setDetailedError(DetailedError $error = null)
+ {
+ $this->detailedError = $error;
+
+ return $this;
+ }
+
+ /**
+ * Returns the detailed error.
+ *
+ * @return DetailedError|null
+ */
+ public function getDetailedError()
+ {
+ return $this->detailedError;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Computer.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Computer.php
new file mode 100644
index 0000000..72db0a0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Computer.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+use LdapRecord\Models\ActiveDirectory\Concerns\HasPrimaryGroup;
+
+class Computer extends Entry
+{
+ use HasPrimaryGroup;
+
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'person',
+ 'organizationalperson',
+ 'user',
+ 'computer',
+ ];
+
+ /**
+ * The groups relationship.
+ *
+ * Retrieves groups that the current computer is apart of.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function groups()
+ {
+ return $this->hasMany(Group::class, 'member')->with($this->primaryGroup());
+ }
+
+ /**
+ * The primary group relationship.
+ *
+ * @return Relations\HasOnePrimaryGroup
+ */
+ public function primaryGroup()
+ {
+ return $this->hasOnePrimaryGroup(Group::class, 'primarygroupid');
+ }
+
+ /**
+ * The managed by relationship.
+ *
+ * @return \LdapRecord\Models\Relations\HasOne
+ */
+ public function managedBy()
+ {
+ return $this->hasOne([Contact::class, Group::class, User::class], 'managedby');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Concerns/HasPrimaryGroup.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Concerns/HasPrimaryGroup.php
new file mode 100644
index 0000000..97fd3a1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Concerns/HasPrimaryGroup.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory\Concerns;
+
+use LdapRecord\Models\ActiveDirectory\Relations\HasOnePrimaryGroup;
+
+trait HasPrimaryGroup
+{
+ /**
+ * Returns a new has one primary group relationship.
+ *
+ * @param mixed $related
+ * @param string $relationKey
+ * @param string $foreignKey
+ *
+ * @return HasOnePrimaryGroup
+ */
+ public function hasOnePrimaryGroup($related, $relationKey, $foreignKey = 'primarygroupid')
+ {
+ return new HasOnePrimaryGroup($this->newQuery(), $this, $related, $relationKey, $foreignKey);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Contact.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Contact.php
new file mode 100644
index 0000000..52c451f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Contact.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+class Contact extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'person',
+ 'organizationalperson',
+ 'contact',
+ ];
+
+ /**
+ * The groups relationship.
+ *
+ * Retrieves groups that the current contact is apart of.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function groups()
+ {
+ return $this->hasMany(Group::class, 'member');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Container.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Container.php
new file mode 100644
index 0000000..1636cf3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Container.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+class Container extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'container',
+ ];
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Entry.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Entry.php
new file mode 100644
index 0000000..79a9d63
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Entry.php
@@ -0,0 +1,167 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+use InvalidArgumentException;
+use LdapRecord\Connection;
+use LdapRecord\Models\Attributes\Sid;
+use LdapRecord\Models\Entry as BaseEntry;
+use LdapRecord\Models\Events\Updated;
+use LdapRecord\Models\Types\ActiveDirectory;
+use LdapRecord\Query\Model\ActiveDirectoryBuilder;
+
+/** @mixin ActiveDirectoryBuilder */
+class Entry extends BaseEntry implements ActiveDirectory
+{
+ /**
+ * The default attributes that should be mutated to dates.
+ *
+ * @var array
+ */
+ protected $defaultDates = [
+ 'whenchanged' => 'windows',
+ 'whencreated' => 'windows',
+ 'dscorepropagationdata' => 'windows',
+ ];
+
+ /**
+ * The attribute key that contains the Object SID.
+ *
+ * @var string
+ */
+ protected $sidKey = 'objectsid';
+
+ /**
+ * @inheritdoc
+ */
+ public function getObjectSidKey()
+ {
+ return $this->sidKey;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getObjectSid()
+ {
+ return $this->getFirstAttribute($this->sidKey);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getConvertedSid()
+ {
+ try {
+ return (string) new Sid($this->getObjectSid());
+ } catch (InvalidArgumentException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Create a new query builder.
+ *
+ * @param Connection $connection
+ *
+ * @return ActiveDirectoryBuilder
+ */
+ public function newQueryBuilder(Connection $connection)
+ {
+ return new ActiveDirectoryBuilder($connection);
+ }
+
+ /**
+ * Determine if the object is deleted.
+ *
+ * @return bool
+ */
+ public function isDeleted()
+ {
+ return strtoupper($this->getFirstAttribute('isDeleted')) === 'TRUE';
+ }
+
+ /**
+ * Restore a deleted object.
+ *
+ * @param string|null $newParentDn
+ *
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return bool
+ */
+ public function restore($newParentDn = null)
+ {
+ if (! $this->isDeleted()) {
+ return false;
+ }
+
+ $root = $newParentDn ?? $this->getDefaultRestoreLocation();
+ $rdn = explode('\0A', $this->getDn(), 2)[0];
+ $newDn = implode(',', [$rdn, $root]);
+
+ // We will initialize a model listener for the "updated" event to set
+ // the models distinguished name so all attributes are synchronized
+ // properly after the model has been successfully restored.
+ $this->listenForModelEvent(Updated::class, function (Updated $event) use ($newDn) {
+ if ($this->is($event->getModel())) {
+ $this->setDn($newDn);
+ }
+ });
+
+ $this->save([
+ 'isDeleted' => null,
+ 'distinguishedName' => $newDn,
+ ]);
+ }
+
+ /**
+ * Get the RootDSE (AD schema) record from the directory.
+ *
+ * @param string|null $connection
+ *
+ * @throws \LdapRecord\Models\ModelNotFoundException
+ *
+ * @return static
+ */
+ public static function getRootDse($connection = null)
+ {
+ return static::on($connection ?? (new static())->getConnectionName())
+ ->in(null)
+ ->read()
+ ->whereHas('objectclass')
+ ->firstOrFail();
+ }
+
+ /**
+ * Get the objects restore location.
+ *
+ * @return string
+ */
+ protected function getDefaultRestoreLocation()
+ {
+ return $this->getFirstAttribute('lastKnownParent') ?? $this->getParentDn($this->getParentDn($this->getDn()));
+ }
+
+ /**
+ * Converts attributes for JSON serialization.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+ protected function convertAttributesForJson(array $attributes = [])
+ {
+ $attributes = parent::convertAttributesForJson($attributes);
+
+ if ($this->hasAttribute($this->sidKey)) {
+ // If the model has a SID set, we need to convert it due to it being in
+ // binary. Otherwise we will receive a JSON serialization exception.
+ return array_replace($attributes, [
+ $this->sidKey => [$this->getConvertedSid()],
+ ]);
+ }
+
+ return $attributes;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/ExchangeDatabase.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/ExchangeDatabase.php
new file mode 100644
index 0000000..77abbbc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/ExchangeDatabase.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+class ExchangeDatabase extends Entry
+{
+ /**
+ * @inheritdoc
+ */
+ public static $objectClasses = ['msExchMDB'];
+
+ /**
+ * @inheritdoc
+ */
+ public static function boot()
+ {
+ parent::boot();
+
+ static::addGlobalScope(new Scopes\InConfigurationContext());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/ExchangeServer.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/ExchangeServer.php
new file mode 100644
index 0000000..d304876
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/ExchangeServer.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+class ExchangeServer extends Entry
+{
+ /**
+ * @inheritdoc
+ */
+ public static $objectClasses = ['msExchExchangeServer'];
+
+ /**
+ * @inheritdoc
+ */
+ public static function boot()
+ {
+ parent::boot();
+
+ static::addGlobalScope(new Scopes\HasServerRoleAttribute());
+ static::addGlobalScope(new Scopes\InConfigurationContext());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/ForeignSecurityPrincipal.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/ForeignSecurityPrincipal.php
new file mode 100644
index 0000000..25287ae
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/ForeignSecurityPrincipal.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+class ForeignSecurityPrincipal extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = ['foreignsecurityprincipal'];
+
+ /**
+ * The groups relationship.
+ *
+ * Retrieves groups that the current security principal is apart of.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function groups()
+ {
+ return $this->hasMany(Group::class, 'member');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Group.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Group.php
new file mode 100644
index 0000000..6076f2f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Group.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+class Group extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'group',
+ ];
+
+ /**
+ * The groups relationship.
+ *
+ * Retrieves groups that the current group is apart of.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function groups()
+ {
+ return $this->hasMany(static::class, 'member');
+ }
+
+ /**
+ * The members relationship.
+ *
+ * Retrieves members that are apart of the group.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function members()
+ {
+ return $this->hasMany([
+ static::class, User::class, Contact::class, Computer::class,
+ ], 'memberof')
+ ->using($this, 'member')
+ ->with($this->primaryGroupMembers());
+ }
+
+ /**
+ * The primary group members relationship.
+ *
+ * Retrieves members that are apart the primary group.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function primaryGroupMembers()
+ {
+ return $this->hasMany([
+ static::class, User::class, Contact::class, Computer::class,
+ ], 'primarygroupid', 'rid');
+ }
+
+ /**
+ * Get the RID of the group.
+ *
+ * @return array
+ */
+ public function getRidAttribute()
+ {
+ $objectSidComponents = explode('-', $this->getConvertedSid());
+
+ return [end($objectSidComponents)];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/OrganizationalUnit.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/OrganizationalUnit.php
new file mode 100644
index 0000000..80aae9f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/OrganizationalUnit.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+class OrganizationalUnit extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'organizationalunit',
+ ];
+
+ /**
+ * Get the creatable RDN attribute name.
+ *
+ * @return string
+ */
+ public function getCreatableRdnAttribute()
+ {
+ return 'ou';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Printer.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Printer.php
new file mode 100644
index 0000000..df74216
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Printer.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+class Printer extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = ['printqueue'];
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Relations/HasOnePrimaryGroup.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Relations/HasOnePrimaryGroup.php
new file mode 100644
index 0000000..540ec77
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Relations/HasOnePrimaryGroup.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory\Relations;
+
+use LdapRecord\Models\Model;
+use LdapRecord\Models\Relations\HasOne;
+
+class HasOnePrimaryGroup extends HasOne
+{
+ /**
+ * Get the foreign model by the given value.
+ *
+ * @param string $value
+ *
+ * @return Model|null
+ */
+ protected function getForeignModelByValue($value)
+ {
+ return $this->query->findBySid(
+ $this->getParentModelObjectSid()
+ );
+ }
+
+ /**
+ * Get the foreign value from the given model.
+ *
+ * Retrieves the last RID from the models Object SID.
+ *
+ * @param Model $model
+ *
+ * @return string
+ */
+ protected function getForeignValueFromModel(Model $model)
+ {
+ $objectSidComponents = explode('-', $model->getConvertedSid());
+
+ return end($objectSidComponents);
+ }
+
+ /**
+ * Get the parent relationship models converted object sid.
+ *
+ * @return string
+ */
+ protected function getParentModelObjectSid()
+ {
+ return preg_replace(
+ '/\d+$/',
+ $this->parent->getFirstAttribute($this->relationKey),
+ $this->parent->getConvertedSid()
+ );
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Scopes/HasServerRoleAttribute.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Scopes/HasServerRoleAttribute.php
new file mode 100644
index 0000000..cd08648
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Scopes/HasServerRoleAttribute.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory\Scopes;
+
+use LdapRecord\Models\Model;
+use LdapRecord\Models\Scope;
+use LdapRecord\Query\Model\Builder;
+
+class HasServerRoleAttribute implements Scope
+{
+ /**
+ * Includes condition of having a serverRole attribute.
+ *
+ * @param Builder $query
+ * @param Model $model
+ *
+ * @return void
+ */
+ public function apply(Builder $query, Model $model)
+ {
+ $query->whereHas('serverRole');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Scopes/InConfigurationContext.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Scopes/InConfigurationContext.php
new file mode 100644
index 0000000..2b1a177
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Scopes/InConfigurationContext.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory\Scopes;
+
+use LdapRecord\Models\ActiveDirectory\Entry;
+use LdapRecord\Models\Model;
+use LdapRecord\Models\Scope;
+use LdapRecord\Query\Model\Builder;
+
+class InConfigurationContext implements Scope
+{
+ /**
+ * Refines the base dn to be inside the configuration context.
+ *
+ * @param Builder $query
+ * @param Model $model
+ *
+ * @throws \LdapRecord\Models\ModelNotFoundException
+ *
+ * @return void
+ */
+ public function apply(Builder $query, Model $model)
+ {
+ $query->in($this->getConfigurationNamingContext($model));
+ }
+
+ /**
+ * Get the LDAP server configuration naming context distinguished name.
+ *
+ * @param Model $model
+ *
+ * @throws \LdapRecord\Models\ModelNotFoundException
+ *
+ * @return mixed
+ */
+ protected function getConfigurationNamingContext(Model $model)
+ {
+ return Entry::getRootDse($model->getConnectionName())
+ ->getFirstAttribute('configurationNamingContext');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Scopes/RejectComputerObjectClass.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Scopes/RejectComputerObjectClass.php
new file mode 100644
index 0000000..a616db1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/Scopes/RejectComputerObjectClass.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory\Scopes;
+
+use LdapRecord\Models\Model;
+use LdapRecord\Models\Scope;
+use LdapRecord\Query\Model\Builder;
+
+class RejectComputerObjectClass implements Scope
+{
+ /**
+ * Prevent computer objects from being included in results.
+ *
+ * @param Builder $query
+ * @param Model $model
+ *
+ * @return void
+ */
+ public function apply(Builder $query, Model $model)
+ {
+ $query->where('objectclass', '!=', 'computer');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/User.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/User.php
new file mode 100644
index 0000000..84dd74b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ActiveDirectory/User.php
@@ -0,0 +1,120 @@
+<?php
+
+namespace LdapRecord\Models\ActiveDirectory;
+
+use Illuminate\Contracts\Auth\Authenticatable;
+use LdapRecord\Models\ActiveDirectory\Concerns\HasPrimaryGroup;
+use LdapRecord\Models\ActiveDirectory\Scopes\RejectComputerObjectClass;
+use LdapRecord\Models\Concerns\CanAuthenticate;
+use LdapRecord\Models\Concerns\HasPassword;
+use LdapRecord\Query\Model\Builder;
+
+class User extends Entry implements Authenticatable
+{
+ use HasPassword;
+ use HasPrimaryGroup;
+ use CanAuthenticate;
+
+ /**
+ * The password's attribute name.
+ *
+ * @var string
+ */
+ protected $passwordAttribute = 'unicodepwd';
+
+ /**
+ * The password's hash method.
+ *
+ * @var string
+ */
+ protected $passwordHashMethod = 'encode';
+
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'person',
+ 'organizationalperson',
+ 'user',
+ ];
+
+ /**
+ * The attributes that should be mutated to dates.
+ *
+ * @var array
+ */
+ protected $dates = [
+ 'lastlogon' => 'windows-int',
+ 'lastlogoff' => 'windows-int',
+ 'pwdlastset' => 'windows-int',
+ 'lockouttime' => 'windows-int',
+ 'accountexpires' => 'windows-int',
+ 'badpasswordtime' => 'windows-int',
+ 'lastlogontimestamp' => 'windows-int',
+ ];
+
+ /**
+ * @inheritdoc
+ */
+ protected static function boot()
+ {
+ parent::boot();
+
+ // Here we will add a global scope to reject the 'computer' object
+ // class. This is needed due to computer objects containing all
+ // of the ActiveDirectory 'user' object classes. Without
+ // this scope, they would be included in results.
+ static::addGlobalScope(new RejectComputerObjectClass());
+ }
+
+ /**
+ * The groups relationship.
+ *
+ * Retrieves groups that the user is apart of.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function groups()
+ {
+ return $this->hasMany(Group::class, 'member')->with($this->primaryGroup());
+ }
+
+ /**
+ * The manager relationship.
+ *
+ * Retrieves the manager of the user.
+ *
+ * @return \LdapRecord\Models\Relations\HasOne
+ */
+ public function manager()
+ {
+ return $this->hasOne(static::class, 'manager');
+ }
+
+ /**
+ * The primary group relationship of the current user.
+ *
+ * Retrieves the primary group the user is apart of.
+ *
+ * @return \LdapRecord\Models\Relations\HasOne
+ */
+ public function primaryGroup()
+ {
+ return $this->hasOnePrimaryGroup(Group::class, 'primarygroupid');
+ }
+
+ /**
+ * Scopes the query to exchange mailbox users.
+ *
+ * @param Builder $query
+ *
+ * @return Builder
+ */
+ public function scopeWhereHasMailbox(Builder $query)
+ {
+ return $query->whereHas('msExchMailboxGuid');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/AccountControl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/AccountControl.php
new file mode 100644
index 0000000..9c6240b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/AccountControl.php
@@ -0,0 +1,502 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+use ReflectionClass;
+
+class AccountControl
+{
+ const SCRIPT = 1;
+
+ const ACCOUNTDISABLE = 2;
+
+ const HOMEDIR_REQUIRED = 8;
+
+ const LOCKOUT = 16;
+
+ const PASSWD_NOTREQD = 32;
+
+ const PASSWD_CANT_CHANGE = 64;
+
+ const ENCRYPTED_TEXT_PWD_ALLOWED = 128;
+
+ const TEMP_DUPLICATE_ACCOUNT = 256;
+
+ const NORMAL_ACCOUNT = 512;
+
+ const INTERDOMAIN_TRUST_ACCOUNT = 2048;
+
+ const WORKSTATION_TRUST_ACCOUNT = 4096;
+
+ const SERVER_TRUST_ACCOUNT = 8192;
+
+ const DONT_EXPIRE_PASSWORD = 65536;
+
+ const MNS_LOGON_ACCOUNT = 131072;
+
+ const SMARTCARD_REQUIRED = 262144;
+
+ const TRUSTED_FOR_DELEGATION = 524288;
+
+ const NOT_DELEGATED = 1048576;
+
+ const USE_DES_KEY_ONLY = 2097152;
+
+ const DONT_REQ_PREAUTH = 4194304;
+
+ const PASSWORD_EXPIRED = 8388608;
+
+ const TRUSTED_TO_AUTH_FOR_DELEGATION = 16777216;
+
+ const PARTIAL_SECRETS_ACCOUNT = 67108864;
+
+ /**
+ * The account control flag values.
+ *
+ * @var array
+ */
+ protected $values = [];
+
+ /**
+ * Constructor.
+ *
+ * @param int $flag
+ */
+ public function __construct($flag = null)
+ {
+ if (! is_null($flag)) {
+ $this->apply($flag);
+ }
+ }
+
+ /**
+ * Get the value when casted to string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return (string) $this->getValue();
+ }
+
+ /**
+ * Get the value when casted to int.
+ *
+ * @return int
+ */
+ public function __toInt()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Add the flag to the account control values.
+ *
+ * @param int $flag
+ *
+ * @return $this
+ */
+ public function add($flag)
+ {
+ // Use the value as a key so if the same value
+ // is used, it will always be overwritten
+ $this->values[$flag] = $flag;
+
+ return $this;
+ }
+
+ /**
+ * Remove the flag from the account control.
+ *
+ * @param int $flag
+ *
+ * @return $this
+ */
+ public function remove($flag)
+ {
+ unset($this->values[$flag]);
+
+ return $this;
+ }
+
+ /**
+ * Extract and apply the flag.
+ *
+ * @param int $flag
+ *
+ * @return void
+ */
+ public function apply($flag)
+ {
+ $this->setValues($this->extractFlags($flag));
+ }
+
+ /**
+ * Determine if the account control contains the given UAC flag(s).
+ *
+ * @param int $flag
+ *
+ * @return bool
+ */
+ public function has($flag)
+ {
+ // Here we will extract the given flag into an array
+ // of possible flags. This will allow us to see if
+ // our AccountControl object contains any of them.
+ $flagsUsed = array_intersect(
+ $this->extractFlags($flag),
+ $this->values
+ );
+
+ return in_array($flag, $flagsUsed);
+ }
+
+ /**
+ * Determine if the account control does not contain the given UAC flag(s).
+ *
+ * @param int $flag
+ *
+ * @return bool
+ */
+ public function doesntHave($flag)
+ {
+ return ! $this->has($flag);
+ }
+
+ /**
+ * Generate an LDAP filter based on the current value.
+ *
+ * @return string
+ */
+ public function filter()
+ {
+ return sprintf('(UserAccountControl:1.2.840.113556.1.4.803:=%s)', $this->getValue());
+ }
+
+ /**
+ * The logon script will be run.
+ *
+ * @return $this
+ */
+ public function runLoginScript()
+ {
+ return $this->add(static::SCRIPT);
+ }
+
+ /**
+ * The user account is locked.
+ *
+ * @return $this
+ */
+ public function accountIsLocked()
+ {
+ return $this->add(static::LOCKOUT);
+ }
+
+ /**
+ * The user account is disabled.
+ *
+ * @return $this
+ */
+ public function accountIsDisabled()
+ {
+ return $this->add(static::ACCOUNTDISABLE);
+ }
+
+ /**
+ * This is an account for users whose primary account is in another domain.
+ *
+ * This account provides user access to this domain, but not to any domain that
+ * trusts this domain. This is sometimes referred to as a local user account.
+ *
+ * @return $this
+ */
+ public function accountIsTemporary()
+ {
+ return $this->add(static::TEMP_DUPLICATE_ACCOUNT);
+ }
+
+ /**
+ * This is a default account type that represents a typical user.
+ *
+ * @return $this
+ */
+ public function accountIsNormal()
+ {
+ return $this->add(static::NORMAL_ACCOUNT);
+ }
+
+ /**
+ * This is a permit to trust an account for a system domain that trusts other domains.
+ *
+ * @return $this
+ */
+ public function accountIsForInterdomain()
+ {
+ return $this->add(static::INTERDOMAIN_TRUST_ACCOUNT);
+ }
+
+ /**
+ * This is a computer account for a computer that is running Microsoft
+ * Windows NT 4.0 Workstation, Microsoft Windows NT 4.0 Server, Microsoft
+ * Windows 2000 Professional, or Windows 2000 Server and is a member of this domain.
+ *
+ * @return $this
+ */
+ public function accountIsForWorkstation()
+ {
+ return $this->add(static::WORKSTATION_TRUST_ACCOUNT);
+ }
+
+ /**
+ * This is a computer account for a domain controller that is a member of this domain.
+ *
+ * @return $this
+ */
+ public function accountIsForServer()
+ {
+ return $this->add(static::SERVER_TRUST_ACCOUNT);
+ }
+
+ /**
+ * This is an MNS logon account.
+ *
+ * @return $this
+ */
+ public function accountIsMnsLogon()
+ {
+ return $this->add(static::MNS_LOGON_ACCOUNT);
+ }
+
+ /**
+ * (Windows 2000/Windows Server 2003) This account does
+ * not require Kerberos pre-authentication for logging on.
+ *
+ * @return $this
+ */
+ public function accountDoesNotRequirePreAuth()
+ {
+ return $this->add(static::DONT_REQ_PREAUTH);
+ }
+
+ /**
+ * When this flag is set, it forces the user to log on by using a smart card.
+ *
+ * @return $this
+ */
+ public function accountRequiresSmartCard()
+ {
+ return $this->add(static::SMARTCARD_REQUIRED);
+ }
+
+ /**
+ * (Windows Server 2008/Windows Server 2008 R2) The account is a read-only domain controller (RODC).
+ *
+ * This is a security-sensitive setting. Removing this setting from an RODC compromises security on that server.
+ *
+ * @return $this
+ */
+ public function accountIsReadOnly()
+ {
+ return $this->add(static::PARTIAL_SECRETS_ACCOUNT);
+ }
+
+ /**
+ * The home folder is required.
+ *
+ * @return $this
+ */
+ public function homeFolderIsRequired()
+ {
+ return $this->add(static::HOMEDIR_REQUIRED);
+ }
+
+ /**
+ * No password is required.
+ *
+ * @return $this
+ */
+ public function passwordIsNotRequired()
+ {
+ return $this->add(static::PASSWD_NOTREQD);
+ }
+
+ /**
+ * The user cannot change the password. This is a permission on the user's object.
+ *
+ * For information about how to programmatically set this permission, visit the following link:
+ *
+ * @see http://msdn2.microsoft.com/en-us/library/aa746398.aspx
+ *
+ * @return $this
+ */
+ public function passwordCannotBeChanged()
+ {
+ return $this->add(static::PASSWD_CANT_CHANGE);
+ }
+
+ /**
+ * Represents the password, which should never expire on the account.
+ *
+ * @return $this
+ */
+ public function passwordDoesNotExpire()
+ {
+ return $this->add(static::DONT_EXPIRE_PASSWORD);
+ }
+
+ /**
+ * (Windows 2000/Windows Server 2003) The user's password has expired.
+ *
+ * @return $this
+ */
+ public function passwordIsExpired()
+ {
+ return $this->add(static::PASSWORD_EXPIRED);
+ }
+
+ /**
+ * The user can send an encrypted password.
+ *
+ * @return $this
+ */
+ public function allowEncryptedTextPassword()
+ {
+ return $this->add(static::ENCRYPTED_TEXT_PWD_ALLOWED);
+ }
+
+ /**
+ * When this flag is set, the service account (the user or computer account)
+ * under which a service runs is trusted for Kerberos delegation.
+ *
+ * Any such service can impersonate a client requesting the service.
+ *
+ * To enable a service for Kerberos delegation, you must set this
+ * flag on the userAccountControl property of the service account.
+ *
+ * @return $this
+ */
+ public function trustForDelegation()
+ {
+ return $this->add(static::TRUSTED_FOR_DELEGATION);
+ }
+
+ /**
+ * (Windows 2000/Windows Server 2003) The account is enabled for delegation.
+ *
+ * This is a security-sensitive setting. Accounts that have this option enabled
+ * should be tightly controlled. This setting lets a service that runs under the
+ * account assume a client's identity and authenticate as that user to other remote
+ * servers on the network.
+ *
+ * @return $this
+ */
+ public function trustToAuthForDelegation()
+ {
+ return $this->add(static::TRUSTED_TO_AUTH_FOR_DELEGATION);
+ }
+
+ /**
+ * When this flag is set, the security context of the user is not delegated to a
+ * service even if the service account is set as trusted for Kerberos delegation.
+ *
+ * @return $this
+ */
+ public function doNotTrustForDelegation()
+ {
+ return $this->add(static::NOT_DELEGATED);
+ }
+
+ /**
+ * (Windows 2000/Windows Server 2003) Restrict this principal to
+ * use only Data Encryption Standard (DES) encryption types for keys.
+ *
+ * @return $this
+ */
+ public function useDesKeyOnly()
+ {
+ return $this->add(static::USE_DES_KEY_ONLY);
+ }
+
+ /**
+ * Get the account control value.
+ *
+ * @return int
+ */
+ public function getValue()
+ {
+ return array_sum($this->values);
+ }
+
+ /**
+ * Get the account control flag values.
+ *
+ * @return array
+ */
+ public function getValues()
+ {
+ return $this->values;
+ }
+
+ /**
+ * Set the account control values.
+ *
+ * @param array $flags
+ *
+ * @return void
+ */
+ public function setValues(array $flags)
+ {
+ $this->values = $flags;
+ }
+
+ /**
+ * Get all flags that are currently applied to the value.
+ *
+ * @return array
+ */
+ public function getAppliedFlags()
+ {
+ $flags = $this->getAllFlags();
+
+ $exists = [];
+
+ foreach ($flags as $name => $flag) {
+ if ($this->has($flag)) {
+ $exists[$name] = $flag;
+ }
+ }
+
+ return $exists;
+ }
+
+ /**
+ * Get all possible account control flags.
+ *
+ * @return array
+ */
+ public function getAllFlags()
+ {
+ return (new ReflectionClass(__CLASS__))->getConstants();
+ }
+
+ /**
+ * Extracts the given flag into an array of flags used.
+ *
+ * @param int $flag
+ *
+ * @return array
+ */
+ public function extractFlags($flag)
+ {
+ $flags = [];
+
+ for ($i = 0; $i <= 26; $i++) {
+ if ((int) $flag & (1 << $i)) {
+ $flags[1 << $i] = 1 << $i;
+ }
+ }
+
+ return $flags;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedName.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedName.php
new file mode 100644
index 0000000..c092173
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedName.php
@@ -0,0 +1,419 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+use LdapRecord\EscapesValues;
+use LdapRecord\Support\Arr;
+
+class DistinguishedName
+{
+ use EscapesValues;
+
+ /**
+ * The underlying raw value.
+ *
+ * @var string|null
+ */
+ protected $value;
+
+ /**
+ * Constructor.
+ *
+ * @param string|null $value
+ */
+ public function __construct($value = null)
+ {
+ $this->value = trim($value);
+ }
+
+ /**
+ * Get the distinguished name value.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return (string) $this->value;
+ }
+
+ /**
+ * Alias of the "build" method.
+ *
+ * @param string|null $value
+ *
+ * @return DistinguishedNameBuilder
+ */
+ public static function of($value = null)
+ {
+ return static::build($value);
+ }
+
+ /**
+ * Get a new DN builder object from the given DN.
+ *
+ * @param string|null $value
+ *
+ * @return DistinguishedNameBuilder
+ */
+ public static function build($value = null)
+ {
+ return new DistinguishedNameBuilder($value);
+ }
+
+ /**
+ * Make a new distinguished name instance.
+ *
+ * @param string|null $value
+ *
+ * @return static
+ */
+ public static function make($value = null)
+ {
+ return new static($value);
+ }
+
+ /**
+ * Explode a distinguished name into relative distinguished names.
+ *
+ * @param string $dn
+ *
+ * @return array
+ */
+ public static function explode($dn)
+ {
+ $dn = ldap_explode_dn($dn, $withoutAttributes = false);
+
+ if (! is_array($dn)) {
+ return [];
+ }
+
+ if (! array_key_exists('count', $dn)) {
+ return [];
+ }
+
+ unset($dn['count']);
+
+ return $dn;
+ }
+
+ /**
+ * Un-escapes a hexadecimal string into its original string representation.
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ public static function unescape($value)
+ {
+ return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function ($matches) {
+ return chr(hexdec($matches[1]));
+ }, $value);
+ }
+
+ /**
+ * Explode the RDN into an attribute and value.
+ *
+ * @param string $rdn
+ *
+ * @return array
+ */
+ public static function explodeRdn($rdn)
+ {
+ return explode('=', $rdn, $limit = 2);
+ }
+
+ /**
+ * Implode the component attribute and value into an RDN.
+ *
+ * @param string $rdn
+ *
+ * @return string
+ */
+ public static function makeRdn(array $component)
+ {
+ return implode('=', $component);
+ }
+
+ /**
+ * Get the underlying value.
+ *
+ * @return string|null
+ */
+ public function get()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Set the underlying value.
+ *
+ * @param string|null $value
+ *
+ * @return $this
+ */
+ public function set($value)
+ {
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * Get the distinguished name values without attributes.
+ *
+ * @return array
+ */
+ public function values()
+ {
+ $values = [];
+
+ foreach ($this->multi() as [, $value]) {
+ $values[] = static::unescape($value);
+ }
+
+ return $values;
+ }
+
+ /**
+ * Get the distinguished name attributes without values.
+ *
+ * @return array
+ */
+ public function attributes()
+ {
+ $attributes = [];
+
+ foreach ($this->multi() as [$attribute]) {
+ $attributes[] = $attribute;
+ }
+
+ return $attributes;
+ }
+
+ /**
+ * Get the distinguished name components with attributes.
+ *
+ * @return array
+ */
+ public function components()
+ {
+ $components = [];
+
+ foreach ($this->multi() as [$attribute, $value]) {
+ // When a distinguished name is exploded, the values are automatically
+ // escaped. This cannot be opted out of. Here we will unescape
+ // the attribute value, then re-escape it to its original
+ // representation from the server using the "dn" flag.
+ $value = $this->escape(static::unescape($value))->dn();
+
+ $components[] = static::makeRdn([$attribute, $value]);
+ }
+
+ return $components;
+ }
+
+ /**
+ * Convert the distinguished name into an associative array.
+ *
+ * @return array
+ */
+ public function assoc()
+ {
+ $map = [];
+
+ foreach ($this->multi() as [$attribute, $value]) {
+ $attribute = $this->normalize($attribute);
+
+ array_key_exists($attribute, $map)
+ ? $map[$attribute][] = $value
+ : $map[$attribute] = [$value];
+ }
+
+ return $map;
+ }
+
+ /**
+ * Split the RDNs into a multi-dimensional array.
+ *
+ * @return array
+ */
+ public function multi()
+ {
+ return array_map(function ($rdn) {
+ return static::explodeRdn($rdn);
+ }, $this->rdns());
+ }
+
+ /**
+ * Split the distinguished name into an array of unescaped RDN's.
+ *
+ * @return array
+ */
+ public function rdns()
+ {
+ return static::explode($this->value);
+ }
+
+ /**
+ * Get the first RDNs value.
+ *
+ * @return string|null
+ */
+ public function name()
+ {
+ return Arr::first($this->values());
+ }
+
+ /**
+ * Get the first RDNs attribute.
+ *
+ * @return string|null
+ */
+ public function head()
+ {
+ return Arr::first($this->attributes());
+ }
+
+ /**
+ * Get the relative distinguished name.
+ *
+ * @return string|null
+ */
+ public function relative()
+ {
+ return Arr::first($this->components());
+ }
+
+ /**
+ * Alias of relative().
+ *
+ * Get the first RDN from the distinguished name.
+ *
+ * @return string|null
+ */
+ public function first()
+ {
+ return $this->relative();
+ }
+
+ /**
+ * Get the parent distinguished name.
+ *
+ * @return string|null
+ */
+ public function parent()
+ {
+ $components = $this->components();
+
+ array_shift($components);
+
+ return implode(',', $components) ?: null;
+ }
+
+ /**
+ * Determine if the current distinguished name is a parent of the given child.
+ *
+ * @param DistinguishedName $child
+ *
+ * @return bool
+ */
+ public function isParentOf(self $child)
+ {
+ return $child->isChildOf($this);
+ }
+
+ /**
+ * Determine if the current distinguished name is a child of the given parent.
+ *
+ * @param DistinguishedName $parent
+ *
+ * @return bool
+ */
+ public function isChildOf(self $parent)
+ {
+ if (
+ empty($components = $this->components()) ||
+ empty($parentComponents = $parent->components())
+ ) {
+ return false;
+ }
+
+ array_shift($components);
+
+ return $this->compare($components, $parentComponents);
+ }
+
+ /**
+ * Determine if the current distinguished name is an ancestor of the descendant.
+ *
+ * @param DistinguishedName $descendant
+ *
+ * @return bool
+ */
+ public function isAncestorOf(self $descendant)
+ {
+ return $descendant->isDescendantOf($this);
+ }
+
+ /**
+ * Determine if the current distinguished name is a descendant of the ancestor.
+ *
+ * @param DistinguishedName $ancestor
+ *
+ * @return bool
+ */
+ public function isDescendantOf(self $ancestor)
+ {
+ if (
+ empty($components = $this->components()) ||
+ empty($ancestorComponents = $ancestor->components())
+ ) {
+ return false;
+ }
+
+ if (! $length = count($components) - count($ancestorComponents)) {
+ return false;
+ }
+
+ array_splice($components, $offset = 0, $length);
+
+ return $this->compare($components, $ancestorComponents);
+ }
+
+ /**
+ * Compare whether the two distinguished name values are equal.
+ *
+ * @param array $values
+ * @param array $other
+ *
+ * @return bool
+ */
+ protected function compare(array $values, array $other)
+ {
+ return $this->recase($values) == $this->recase($other);
+ }
+
+ /**
+ * Recase the array values.
+ *
+ * @param array $values
+ *
+ * @return array
+ */
+ protected function recase(array $values)
+ {
+ return array_map([$this, 'normalize'], $values);
+ }
+
+ /**
+ * Normalize the string value.
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ protected function normalize($value)
+ {
+ return strtolower($value);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedNameBuilder.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedNameBuilder.php
new file mode 100644
index 0000000..83dfe71
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedNameBuilder.php
@@ -0,0 +1,251 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+use LdapRecord\EscapesValues;
+use LdapRecord\Support\Arr;
+
+class DistinguishedNameBuilder
+{
+ use EscapesValues;
+
+ /**
+ * The components of the DN.
+ *
+ * @var array
+ */
+ protected $components = [];
+
+ /**
+ * Whether to output the DN in reverse.
+ *
+ * @var bool
+ */
+ protected $reverse = false;
+
+ /**
+ * Constructor.
+ *
+ * @param string|null $value
+ */
+ public function __construct($dn = null)
+ {
+ $this->components = array_map(function ($rdn) {
+ return DistinguishedName::explodeRdn($rdn);
+ }, DistinguishedName::make($dn)->components());
+ }
+
+ /**
+ * Forward missing method calls onto the Distinguished Name object.
+ *
+ * @param string $method
+ * @param array $args
+ *
+ * @return mixed
+ */
+ public function __call($method, $args)
+ {
+ return $this->get()->{$method}(...$args);
+ }
+
+ /**
+ * Get the distinguished name value.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return (string) $this->get();
+ }
+
+ /**
+ * Prepend an RDN onto the DN.
+ *
+ * @param string|array $attribute
+ * @param string|null $value
+ *
+ * @return $this
+ */
+ public function prepend($attribute, $value = null)
+ {
+ array_unshift(
+ $this->components,
+ ...$this->componentize($attribute, $value)
+ );
+
+ return $this;
+ }
+
+ /**
+ * Append an RDN onto the DN.
+ *
+ * @param string|array $attribute
+ * @param string|null $value
+ *
+ * @return $this
+ */
+ public function append($attribute, $value = null)
+ {
+ array_push(
+ $this->components,
+ ...$this->componentize($attribute, $value)
+ );
+
+ return $this;
+ }
+
+ /**
+ * Componentize the attribute and value.
+ *
+ * @param string|array $attribute
+ * @param string|null $value
+ *
+ * @return array
+ */
+ protected function componentize($attribute, $value = null)
+ {
+ // Here we will make the assumption that an array of
+ // RDN's have been given if the value is null, and
+ // attempt to break them into their components.
+ if (is_null($value)) {
+ $attributes = Arr::wrap($attribute);
+
+ $components = array_map([$this, 'makeComponentizedArray'], $attributes);
+ } else {
+ $components = [[$attribute, $value]];
+ }
+
+ return array_map(function ($component) {
+ [$attribute, $value] = $component;
+
+ return $this->makeAppendableComponent($attribute, $value);
+ }, $components);
+ }
+
+ /**
+ * Make a componentized array by exploding the value if it's a string.
+ *
+ * @param string $value
+ *
+ * @return array
+ */
+ protected function makeComponentizedArray($value)
+ {
+ return is_array($value) ? $value : DistinguishedName::explodeRdn($value);
+ }
+
+ /**
+ * Make an appendable component array from the attribute and value.
+ *
+ * @param string|array $attribute
+ * @param string|null $value
+ *
+ * @return array
+ */
+ protected function makeAppendableComponent($attribute, $value = null)
+ {
+ return [trim($attribute), $this->escape(trim($value))->dn()];
+ }
+
+ /**
+ * Pop an RDN off of the end of the DN.
+ *
+ * @param int $amount
+ * @param array $removed
+ *
+ * @return $this
+ */
+ public function pop($amount = 1, &$removed = [])
+ {
+ $removed = array_map(function ($component) {
+ return DistinguishedName::makeRdn($component);
+ }, array_splice($this->components, -$amount, $amount));
+
+ return $this;
+ }
+
+ /**
+ * Shift an RDN off of the beginning of the DN.
+ *
+ * @param int $amount
+ * @param array $removed
+ *
+ * @return $this
+ */
+ public function shift($amount = 1, &$removed = [])
+ {
+ $removed = array_map(function ($component) {
+ return DistinguishedName::makeRdn($component);
+ }, array_splice($this->components, 0, $amount));
+
+ return $this;
+ }
+
+ /**
+ * Whether to output the DN in reverse.
+ *
+ * @return $this
+ */
+ public function reverse()
+ {
+ $this->reverse = true;
+
+ return $this;
+ }
+
+ /**
+ * Get the components of the DN.
+ *
+ * @param null|string $type
+ *
+ * @return array
+ */
+ public function components($type = null)
+ {
+ return is_null($type)
+ ? $this->components
+ : $this->componentsOfType($type);
+ }
+
+ /**
+ * Get the components of a particular type.
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+ protected function componentsOfType($type)
+ {
+ $components = array_filter($this->components, function ($component) use ($type) {
+ return ([$name] = $component) && strtolower($name) === strtolower($type);
+ });
+
+ return array_values($components);
+ }
+
+ /**
+ * Get the fully qualified DN.
+ *
+ * @return DistinguishedName
+ */
+ public function get()
+ {
+ return new DistinguishedName($this->build());
+ }
+
+ /**
+ * Build the distinguished name from the components.
+ *
+ * @return $this
+ */
+ protected function build()
+ {
+ $components = $this->reverse
+ ? array_reverse($this->components)
+ : $this->components;
+
+ return implode(',', array_map(function ($component) {
+ return DistinguishedName::makeRdn($component);
+ }, $components));
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/EscapedValue.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/EscapedValue.php
new file mode 100644
index 0000000..cc04a67
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/EscapedValue.php
@@ -0,0 +1,111 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+class EscapedValue
+{
+ /**
+ * The value to be escaped.
+ *
+ * @var string
+ */
+ protected $value;
+
+ /**
+ * The characters to ignore when escaping.
+ *
+ * @var string
+ */
+ protected $ignore;
+
+ /**
+ * The escape flags.
+ *
+ * @var int
+ */
+ protected $flags;
+
+ /**
+ * Constructor.
+ *
+ * @param string $value
+ * @param string $ignore
+ * @param int $flags
+ */
+ public function __construct($value, $ignore = '', $flags = 0)
+ {
+ $this->value = $value;
+ $this->ignore = $ignore;
+ $this->flags = $flags;
+ }
+
+ /**
+ * Get the escaped value.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return (string) $this->get();
+ }
+
+ /**
+ * Get the escaped value.
+ *
+ * @return mixed
+ */
+ public function get()
+ {
+ return ldap_escape($this->value, $this->ignore, $this->flags);
+ }
+
+ /**
+ * Set the characters to exclude from being escaped.
+ *
+ * @param string $characters
+ *
+ * @return $this
+ */
+ public function ignore($characters)
+ {
+ $this->ignore = $characters;
+
+ return $this;
+ }
+
+ /**
+ * Prepare the value to be escaped for use in a distinguished name.
+ *
+ * @return $this
+ */
+ public function dn()
+ {
+ $this->flags = LDAP_ESCAPE_DN;
+
+ return $this;
+ }
+
+ /**
+ * Prepare the value to be escaped for use in a filter.
+ *
+ * @return $this
+ */
+ public function filter()
+ {
+ $this->flags = LDAP_ESCAPE_FILTER;
+
+ return $this;
+ }
+
+ /**
+ * Prepare the value to be escaped for use in a distinguished name and filter.
+ *
+ * @return $this
+ */
+ public function both()
+ {
+ $this->flags = LDAP_ESCAPE_FILTER + LDAP_ESCAPE_DN;
+
+ return $this;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Guid.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Guid.php
new file mode 100644
index 0000000..d139f5f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Guid.php
@@ -0,0 +1,167 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+use InvalidArgumentException;
+use LdapRecord\Utilities;
+
+class Guid
+{
+ /**
+ * The string GUID value.
+ *
+ * @var string
+ */
+ protected $value;
+
+ /**
+ * The guid structure in order by section to parse using substr().
+ *
+ * @author Chad Sikorra <Chad.Sikorra@gmail.com>
+ *
+ * @see https://github.com/ldaptools/ldaptools
+ *
+ * @var array
+ */
+ protected $guidSections = [
+ [[-26, 2], [-28, 2], [-30, 2], [-32, 2]],
+ [[-22, 2], [-24, 2]],
+ [[-18, 2], [-20, 2]],
+ [[-16, 4]],
+ [[-12, 12]],
+ ];
+
+ /**
+ * The hexadecimal octet order based on string position.
+ *
+ * @author Chad Sikorra <Chad.Sikorra@gmail.com>
+ *
+ * @see https://github.com/ldaptools/ldaptools
+ *
+ * @var array
+ */
+ protected $octetSections = [
+ [6, 4, 2, 0],
+ [10, 8],
+ [14, 12],
+ [16, 18, 20, 22, 24, 26, 28, 30],
+ ];
+
+ /**
+ * Determines if the specified GUID is valid.
+ *
+ * @param string $guid
+ *
+ * @return bool
+ */
+ public static function isValid($guid)
+ {
+ return Utilities::isValidGuid($guid);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param mixed $value
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct($value)
+ {
+ if (static::isValid($value)) {
+ $this->value = $value;
+ } elseif ($value = $this->binaryGuidToString($value)) {
+ $this->value = $value;
+ } else {
+ throw new InvalidArgumentException('Invalid Binary / String GUID.');
+ }
+ }
+
+ /**
+ * Returns the string value of the GUID.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Returns the string value of the SID.
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Get the binary representation of the GUID string.
+ *
+ * @return string
+ */
+ public function getBinary()
+ {
+ return hex2bin($this->getHex());
+ }
+
+ /**
+ * Get the hexadecimal representation of the GUID string.
+ *
+ * @return string
+ */
+ public function getHex()
+ {
+ $data = '';
+
+ $guid = str_replace('-', '', $this->value);
+
+ foreach ($this->octetSections as $section) {
+ $data .= $this->parseSection($guid, $section, $octet = true);
+ }
+
+ return $data;
+ }
+
+ /**
+ * Returns the string variant of a binary GUID.
+ *
+ * @param string $binary
+ *
+ * @return string|null
+ */
+ protected function binaryGuidToString($binary)
+ {
+ return Utilities::binaryGuidToString($binary);
+ }
+
+ /**
+ * Return the specified section of the hexadecimal string.
+ *
+ * @author Chad Sikorra <Chad.Sikorra@gmail.com>
+ *
+ * @see https://github.com/ldaptools/ldaptools
+ *
+ * @param string $hex The full hex string.
+ * @param array $sections An array of start and length (unless octet is true, then length is always 2).
+ * @param bool $octet Whether this is for octet string form.
+ *
+ * @return string The concatenated sections in upper-case.
+ */
+ protected function parseSection($hex, array $sections, $octet = false)
+ {
+ $parsedString = '';
+
+ foreach ($sections as $section) {
+ $start = $octet ? $section : $section[0];
+
+ $length = $octet ? 2 : $section[1];
+
+ $parsedString .= substr($hex, $start, $length);
+ }
+
+ return $parsedString;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/MbString.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/MbString.php
new file mode 100644
index 0000000..672e60d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/MbString.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+class MbString
+{
+ /**
+ * Get the integer value of a specific character.
+ *
+ * @param $string
+ *
+ * @return int
+ */
+ public static function ord($string)
+ {
+ if (static::isLoaded()) {
+ $result = unpack('N', mb_convert_encoding($string, 'UCS-4BE', 'UTF-8'));
+
+ if (is_array($result)) {
+ return $result[1];
+ }
+ }
+
+ return ord($string);
+ }
+
+ /**
+ * Get the character for a specific integer value.
+ *
+ * @param $int
+ *
+ * @return string
+ */
+ public static function chr($int)
+ {
+ if (static::isLoaded()) {
+ return mb_convert_encoding(pack('n', $int), 'UTF-8', 'UTF-16BE');
+ }
+
+ return chr($int);
+ }
+
+ /**
+ * Split a string into its individual characters and return it as an array.
+ *
+ * @param string $value
+ *
+ * @return string[]
+ */
+ public static function split($value)
+ {
+ return preg_split('/(?<!^)(?!$)/u', $value);
+ }
+
+ /**
+ * Detects if the given string is UTF 8.
+ *
+ * @param $string
+ *
+ * @return string|false
+ */
+ public static function isUtf8($string)
+ {
+ if (static::isLoaded()) {
+ return mb_detect_encoding($string, 'UTF-8', $strict = true);
+ }
+
+ return $string;
+ }
+
+ /**
+ * Checks if the mbstring extension is enabled in PHP.
+ *
+ * @return bool
+ */
+ public static function isLoaded()
+ {
+ return extension_loaded('mbstring');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Password.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Password.php
new file mode 100644
index 0000000..7f0b412
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Password.php
@@ -0,0 +1,340 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+use InvalidArgumentException;
+use LdapRecord\LdapRecordException;
+use ReflectionMethod;
+
+class Password
+{
+ const CRYPT_SALT_TYPE_MD5 = 1;
+ const CRYPT_SALT_TYPE_SHA256 = 5;
+ const CRYPT_SALT_TYPE_SHA512 = 6;
+
+ /**
+ * Make an encoded password for transmission over LDAP.
+ *
+ * @param string $password
+ *
+ * @return string
+ */
+ public static function encode($password)
+ {
+ return iconv('UTF-8', 'UTF-16LE', '"'.$password.'"');
+ }
+
+ /**
+ * Make a salted md5 password.
+ *
+ * @param string $password
+ * @param null|string $salt
+ *
+ * @return string
+ */
+ public static function smd5($password, $salt = null)
+ {
+ return '{SMD5}'.static::makeHash($password, 'md5', null, $salt ?? random_bytes(4));
+ }
+
+ /**
+ * Make a salted SHA password.
+ *
+ * @param string $password
+ * @param null|string $salt
+ *
+ * @return string
+ */
+ public static function ssha($password, $salt = null)
+ {
+ return '{SSHA}'.static::makeHash($password, 'sha1', null, $salt ?? random_bytes(4));
+ }
+
+ /**
+ * Make a salted SSHA256 password.
+ *
+ * @param string $password
+ * @param null|string $salt
+ *
+ * @return string
+ */
+ public static function ssha256($password, $salt = null)
+ {
+ return '{SSHA256}'.static::makeHash($password, 'hash', 'sha256', $salt ?? random_bytes(4));
+ }
+
+ /**
+ * Make a salted SSHA384 password.
+ *
+ * @param string $password
+ * @param null|string $salt
+ *
+ * @return string
+ */
+ public static function ssha384($password, $salt = null)
+ {
+ return '{SSHA384}'.static::makeHash($password, 'hash', 'sha384', $salt ?? random_bytes(4));
+ }
+
+ /**
+ * Make a salted SSHA512 password.
+ *
+ * @param string $password
+ * @param null|string $salt
+ *
+ * @return string
+ */
+ public static function ssha512($password, $salt = null)
+ {
+ return '{SSHA512}'.static::makeHash($password, 'hash', 'sha512', $salt ?? random_bytes(4));
+ }
+
+ /**
+ * Make a non-salted SHA password.
+ *
+ * @param string $password
+ *
+ * @return string
+ */
+ public static function sha($password)
+ {
+ return '{SHA}'.static::makeHash($password, 'sha1');
+ }
+
+ /**
+ * Make a non-salted SHA256 password.
+ *
+ * @param string $password
+ *
+ * @return string
+ */
+ public static function sha256($password)
+ {
+ return '{SHA256}'.static::makeHash($password, 'hash', 'sha256');
+ }
+
+ /**
+ * Make a non-salted SHA384 password.
+ *
+ * @param string $password
+ *
+ * @return string
+ */
+ public static function sha384($password)
+ {
+ return '{SHA384}'.static::makeHash($password, 'hash', 'sha384');
+ }
+
+ /**
+ * Make a non-salted SHA512 password.
+ *
+ * @param string $password
+ *
+ * @return string
+ */
+ public static function sha512($password)
+ {
+ return '{SHA512}'.static::makeHash($password, 'hash', 'sha512');
+ }
+
+ /**
+ * Make a non-salted md5 password.
+ *
+ * @param string $password
+ *
+ * @return string
+ */
+ public static function md5($password)
+ {
+ return '{MD5}'.static::makeHash($password, 'md5');
+ }
+
+ /**
+ * Crypt password with an MD5 salt.
+ *
+ * @param string $password
+ * @param string $salt
+ *
+ * @return string
+ */
+ public static function md5Crypt($password, $salt = null)
+ {
+ return '{CRYPT}'.static::makeCrypt($password, static::CRYPT_SALT_TYPE_MD5, $salt);
+ }
+
+ /**
+ * Crypt password with a SHA256 salt.
+ *
+ * @param string $password
+ * @param string $salt
+ *
+ * @return string
+ */
+ public static function sha256Crypt($password, $salt = null)
+ {
+ return '{CRYPT}'.static::makeCrypt($password, static::CRYPT_SALT_TYPE_SHA256, $salt);
+ }
+
+ /**
+ * Crypt a password with a SHA512 salt.
+ *
+ * @param string $password
+ * @param string $salt
+ *
+ * @return string
+ */
+ public static function sha512Crypt($password, $salt = null)
+ {
+ return '{CRYPT}'.static::makeCrypt($password, static::CRYPT_SALT_TYPE_SHA512, $salt);
+ }
+
+ /**
+ * Make a new password hash.
+ *
+ * @param string $password The password to make a hash of.
+ * @param string $method The hash function to use.
+ * @param string|null $algo The algorithm to use for hashing.
+ * @param string|null $salt The salt to append onto the hash.
+ *
+ * @return string
+ */
+ protected static function makeHash($password, $method, $algo = null, $salt = null)
+ {
+ $params = $algo ? [$algo, $password.$salt] : [$password.$salt];
+
+ return base64_encode(pack('H*', call_user_func($method, ...$params)).$salt);
+ }
+
+ /**
+ * Make a hashed password.
+ *
+ * @param string $password
+ * @param int $type
+ * @param null|string $salt
+ *
+ * @return string
+ */
+ protected static function makeCrypt($password, $type, $salt = null)
+ {
+ return crypt($password, $salt ?? static::makeCryptSalt($type));
+ }
+
+ /**
+ * Make a salt for the crypt() method using the given type.
+ *
+ * @param int $type
+ *
+ * @return string
+ */
+ protected static function makeCryptSalt($type)
+ {
+ [$prefix, $length] = static::makeCryptPrefixAndLength($type);
+
+ $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+ while (strlen($prefix) < $length) {
+ $prefix .= substr($chars, random_int(0, strlen($chars) - 1), 1);
+ }
+
+ return $prefix;
+ }
+
+ /**
+ * Determine the crypt prefix and length.
+ *
+ * @param int $type
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return array
+ */
+ protected static function makeCryptPrefixAndLength($type)
+ {
+ switch ($type) {
+ case static::CRYPT_SALT_TYPE_MD5:
+ return ['$1$', 12];
+ case static::CRYPT_SALT_TYPE_SHA256:
+ return ['$5$', 16];
+ case static::CRYPT_SALT_TYPE_SHA512:
+ return ['$6$', 16];
+ default:
+ throw new InvalidArgumentException("Invalid crypt type [$type].");
+ }
+ }
+
+ /**
+ * Attempt to retrieve the hash method used for the password.
+ *
+ * @param string $password
+ *
+ * @return string|void
+ */
+ public static function getHashMethod($password)
+ {
+ if (! preg_match('/^\{(\w+)\}/', $password, $matches)) {
+ return;
+ }
+
+ return $matches[1];
+ }
+
+ /**
+ * Attempt to retrieve the hash method and algorithm used for the password.
+ *
+ * @param string $password
+ *
+ * @return array|void
+ */
+ public static function getHashMethodAndAlgo($password)
+ {
+ if (! preg_match('/^\{(\w+)\}\$([0-9a-z]{1})\$/', $password, $matches)) {
+ return;
+ }
+
+ return [$matches[1], $matches[2]];
+ }
+
+ /**
+ * Attempt to retrieve a salt from the encrypted password.
+ *
+ * @throws LdapRecordException
+ *
+ * @return string
+ */
+ public static function getSalt($encryptedPassword)
+ {
+ // crypt() methods.
+ if (preg_match('/^\{(\w+)\}(\$.*\$).*$/', $encryptedPassword, $matches)) {
+ return $matches[2];
+ }
+
+ // All other methods.
+ if (preg_match('/{([^}]+)}(.*)/', $encryptedPassword, $matches)) {
+ return substr(base64_decode($matches[2]), -4);
+ }
+
+ throw new LdapRecordException('Could not extract salt from encrypted password.');
+ }
+
+ /**
+ * Determine if the hash method requires a salt to be given.
+ *
+ * @param string $method
+ *
+ * @throws \ReflectionException
+ *
+ * @return bool
+ */
+ public static function hashMethodRequiresSalt($method): bool
+ {
+ $parameters = (new ReflectionMethod(static::class, $method))->getParameters();
+
+ foreach ($parameters as $parameter) {
+ if ($parameter->name === 'salt') {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Sid.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Sid.php
new file mode 100644
index 0000000..4ec46ea
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Sid.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+use InvalidArgumentException;
+use LdapRecord\Utilities;
+
+class Sid
+{
+ /**
+ * The string SID value.
+ *
+ * @var string
+ */
+ protected $value;
+
+ /**
+ * Determines if the specified SID is valid.
+ *
+ * @param string $sid
+ *
+ * @return bool
+ */
+ public static function isValid($sid)
+ {
+ return Utilities::isValidSid($sid);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param mixed $value
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct($value)
+ {
+ if (static::isValid($value)) {
+ $this->value = $value;
+ } elseif ($value = $this->binarySidToString($value)) {
+ $this->value = $value;
+ } else {
+ throw new InvalidArgumentException('Invalid Binary / String SID.');
+ }
+ }
+
+ /**
+ * Returns the string value of the SID.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Returns the string value of the SID.
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Returns the binary variant of the SID.
+ *
+ * @return string
+ */
+ public function getBinary()
+ {
+ $sid = explode('-', ltrim($this->value, 'S-'));
+
+ $level = (int) array_shift($sid);
+
+ $authority = (int) array_shift($sid);
+
+ $subAuthorities = array_map('intval', $sid);
+
+ $params = array_merge(
+ ['C2xxNV*', $level, count($subAuthorities), $authority],
+ $subAuthorities
+ );
+
+ return call_user_func_array('pack', $params);
+ }
+
+ /**
+ * Returns the string variant of a binary SID.
+ *
+ * @param string $binary
+ *
+ * @return string|null
+ */
+ protected function binarySidToString($binary)
+ {
+ return Utilities::binarySidToString($binary);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/TSProperty.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/TSProperty.php
new file mode 100644
index 0000000..ad56aa1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/TSProperty.php
@@ -0,0 +1,396 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+class TSProperty
+{
+ /**
+ * Nibble control values. The first value for each is if the nibble is <= 9, otherwise the second value is used.
+ */
+ const NIBBLE_CONTROL = [
+ 'X' => ['001011', '011010'],
+ 'Y' => ['001110', '011010'],
+ ];
+
+ /**
+ * The nibble header.
+ */
+ const NIBBLE_HEADER = '1110';
+
+ /**
+ * Conversion factor needed for time values in the TSPropertyArray (stored in microseconds).
+ */
+ const TIME_CONVERSION = 60 * 1000;
+
+ /**
+ * A simple map to help determine how the property needs to be decoded/encoded from/to its binary value.
+ *
+ * There are some names that are simple repeats but have 'W' at the end. Not sure as to what that signifies. I
+ * cannot find any information on them in Microsoft documentation. However, their values appear to stay in sync with
+ * their non 'W' counterparts. But not doing so when manipulating the data manually does not seem to affect anything.
+ * This probably needs more investigation.
+ *
+ * @var array
+ */
+ protected $propTypes = [
+ 'string' => [
+ 'CtxWFHomeDir',
+ 'CtxWFHomeDirW',
+ 'CtxWFHomeDirDrive',
+ 'CtxWFHomeDirDriveW',
+ 'CtxInitialProgram',
+ 'CtxInitialProgramW',
+ 'CtxWFProfilePath',
+ 'CtxWFProfilePathW',
+ 'CtxWorkDirectory',
+ 'CtxWorkDirectoryW',
+ 'CtxCallbackNumber',
+ ],
+ 'time' => [
+ 'CtxMaxDisconnectionTime',
+ 'CtxMaxConnectionTime',
+ 'CtxMaxIdleTime',
+ ],
+ 'int' => [
+ 'CtxCfgFlags1',
+ 'CtxCfgPresent',
+ 'CtxKeyboardLayout',
+ 'CtxMinEncryptionLevel',
+ 'CtxNWLogonServer',
+ 'CtxShadow',
+ ],
+ ];
+
+ /**
+ * The property name.
+ *
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * The property value.
+ *
+ * @var string|int
+ */
+ protected $value;
+
+ /**
+ * The property value type.
+ *
+ * @var int
+ */
+ protected $valueType = 1;
+
+ /**
+ * Pass binary TSProperty data to construct its object representation.
+ *
+ * @param string|null $value
+ */
+ public function __construct($value = null)
+ {
+ if ($value) {
+ $this->decode(bin2hex($value));
+ }
+ }
+
+ /**
+ * Set the name for the TSProperty.
+ *
+ * @param string $name
+ *
+ * @return TSProperty
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * Get the name for the TSProperty.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Set the value for the TSProperty.
+ *
+ * @param string|int $value
+ *
+ * @return TSProperty
+ */
+ public function setValue($value)
+ {
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * Get the value for the TSProperty.
+ *
+ * @return string|int
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Convert the TSProperty name/value back to its binary
+ * representation for the userParameters blob.
+ *
+ * @return string
+ */
+ public function toBinary()
+ {
+ $name = bin2hex($this->name);
+
+ $binValue = $this->getEncodedValueForProp($this->name, $this->value);
+
+ $valueLen = strlen(bin2hex($binValue)) / 3;
+
+ $binary = hex2bin(
+ $this->dec2hex(strlen($name))
+ .$this->dec2hex($valueLen)
+ .$this->dec2hex($this->valueType)
+ .$name
+ );
+
+ return $binary.$binValue;
+ }
+
+ /**
+ * Given a TSProperty blob, decode the name/value/type/etc.
+ *
+ * @param string $tsProperty
+ */
+ protected function decode($tsProperty)
+ {
+ $nameLength = hexdec(substr($tsProperty, 0, 2));
+
+ // 1 data byte is 3 encoded bytes
+ $valueLength = hexdec(substr($tsProperty, 2, 2)) * 3;
+
+ $this->valueType = hexdec(substr($tsProperty, 4, 2));
+ $this->name = pack('H*', substr($tsProperty, 6, $nameLength));
+ $this->value = $this->getDecodedValueForProp($this->name, substr($tsProperty, 6 + $nameLength, $valueLength));
+ }
+
+ /**
+ * Based on the property name/value in question, get its encoded form.
+ *
+ * @param string $propName
+ * @param string|int $propValue
+ *
+ * @return string
+ */
+ protected function getEncodedValueForProp($propName, $propValue)
+ {
+ if (in_array($propName, $this->propTypes['string'])) {
+ // Simple strings are null terminated. Unsure if this is
+ // needed or simply a product of how ADUC does stuff?
+ $value = $this->encodePropValue($propValue."\0", true);
+ } elseif (in_array($propName, $this->propTypes['time'])) {
+ // Needs to be in microseconds (assuming it is in minute format)...
+ $value = $this->encodePropValue($propValue * self::TIME_CONVERSION);
+ } else {
+ $value = $this->encodePropValue($propValue);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Based on the property name in question, get its actual value from the binary blob value.
+ *
+ * @param string $propName
+ * @param string $propValue
+ *
+ * @return string|int
+ */
+ protected function getDecodedValueForProp($propName, $propValue)
+ {
+ if (in_array($propName, $this->propTypes['string'])) {
+ // Strip away null terminators. I think this should
+ // be desired, otherwise it just ends in confusion.
+ $value = str_replace("\0", '', $this->decodePropValue($propValue, true));
+ } elseif (in_array($propName, $this->propTypes['time'])) {
+ // Convert from microseconds to minutes (how ADUC displays
+ // it anyway, and seems the most practical).
+ $value = hexdec($this->decodePropValue($propValue)) / self::TIME_CONVERSION;
+ } elseif (in_array($propName, $this->propTypes['int'])) {
+ $value = hexdec($this->decodePropValue($propValue));
+ } else {
+ $value = $this->decodePropValue($propValue);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Decode the property by inspecting the nibbles of each blob, checking
+ * the control, and adding up the results into a final value.
+ *
+ * @param string $hex
+ * @param bool $string Whether or not this is simple string data.
+ *
+ * @return string
+ */
+ protected function decodePropValue($hex, $string = false)
+ {
+ $decodePropValue = '';
+
+ $blobs = str_split($hex, 6);
+
+ foreach ($blobs as $blob) {
+ $bin = decbin(hexdec($blob));
+
+ $controlY = substr($bin, 4, 6);
+ $nibbleY = substr($bin, 10, 4);
+ $controlX = substr($bin, 14, 6);
+ $nibbleX = substr($bin, 20, 4);
+
+ $byte = $this->nibbleControl($nibbleX, $controlX).$this->nibbleControl($nibbleY, $controlY);
+
+ if ($string) {
+ $decodePropValue .= MbString::chr(bindec($byte));
+ } else {
+ $decodePropValue = $this->dec2hex(bindec($byte)).$decodePropValue;
+ }
+ }
+
+ return $decodePropValue;
+ }
+
+ /**
+ * Get the encoded property value as a binary blob.
+ *
+ * @param string $value
+ * @param bool $string
+ *
+ * @return string
+ */
+ protected function encodePropValue($value, $string = false)
+ {
+ // An int must be properly padded. (then split and reversed).
+ // For a string, we just split the chars. This seems
+ // to be the easiest way to handle UTF-8 characters
+ // instead of trying to work with their hex values.
+ $chars = $string ? MbString::split($value) : array_reverse(str_split($this->dec2hex($value, 8), 2));
+
+ $encoded = '';
+
+ foreach ($chars as $char) {
+ // Get the bits for the char. Using this method to ensure it is fully padded.
+ $bits = sprintf('%08b', $string ? MbString::ord($char) : hexdec($char));
+ $nibbleX = substr($bits, 0, 4);
+ $nibbleY = substr($bits, 4, 4);
+
+ // Construct the value with the header, high nibble, then low nibble.
+ $value = self::NIBBLE_HEADER;
+
+ foreach (['Y' => $nibbleY, 'X' => $nibbleX] as $nibbleType => $nibble) {
+ $value .= $this->getNibbleWithControl($nibbleType, $nibble);
+ }
+
+ // Convert it back to a binary bit stream
+ foreach ([0, 8, 16] as $start) {
+ $encoded .= $this->packBitString(substr($value, $start, 8), 8);
+ }
+ }
+
+ return $encoded;
+ }
+
+ /**
+ * PHP's pack() function has no 'b' or 'B' template. This is
+ * a workaround that turns a literal bit-string into a
+ * packed byte-string with 8 bits per byte.
+ *
+ * @param string $bits
+ * @param bool $len
+ *
+ * @return string
+ */
+ protected function packBitString($bits, $len)
+ {
+ $bits = substr($bits, 0, $len);
+ // Pad input with zeros to next multiple of 4 above $len
+ $bits = str_pad($bits, 4 * (int) (($len + 3) / 4), '0');
+
+ // Split input into chunks of 4 bits, convert each to hex and pack them
+ $nibbles = str_split($bits, 4);
+ foreach ($nibbles as $i => $nibble) {
+ $nibbles[$i] = base_convert($nibble, 2, 16);
+ }
+
+ return pack('H*', implode('', $nibbles));
+ }
+
+ /**
+ * Based on the control, adjust the nibble accordingly.
+ *
+ * @param string $nibble
+ * @param string $control
+ *
+ * @return string
+ */
+ protected function nibbleControl($nibble, $control)
+ {
+ // This control stays constant for the low/high nibbles,
+ // so it doesn't matter which we compare to
+ if ($control == self::NIBBLE_CONTROL['X'][1]) {
+ $dec = bindec($nibble);
+ $dec += 9;
+ $nibble = str_pad(decbin($dec), 4, '0', STR_PAD_LEFT);
+ }
+
+ return $nibble;
+ }
+
+ /**
+ * Get the nibble value with the control prefixed.
+ *
+ * If the nibble dec is <= 9, the control X equals 001011 and Y equals 001110, otherwise if the nibble dec is > 9
+ * the control for X or Y equals 011010. Additionally, if the dec value of the nibble is > 9, then the nibble value
+ * must be subtracted by 9 before the final value is constructed.
+ *
+ * @param string $nibbleType Either X or Y
+ * @param string $nibble
+ *
+ * @return string
+ */
+ protected function getNibbleWithControl($nibbleType, $nibble)
+ {
+ $dec = bindec($nibble);
+
+ if ($dec > 9) {
+ $dec -= 9;
+ $control = self::NIBBLE_CONTROL[$nibbleType][1];
+ } else {
+ $control = self::NIBBLE_CONTROL[$nibbleType][0];
+ }
+
+ return $control.sprintf('%04d', decbin($dec));
+ }
+
+ /**
+ * Need to make sure hex values are always an even length, so pad as needed.
+ *
+ * @param int $int
+ * @param int $padLength The hex string must be padded to this length (with zeros).
+ *
+ * @return string
+ */
+ protected function dec2hex($int, $padLength = 2)
+ {
+ return str_pad(dechex($int), $padLength, 0, STR_PAD_LEFT);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/TSPropertyArray.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/TSPropertyArray.php
new file mode 100644
index 0000000..1831688
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/TSPropertyArray.php
@@ -0,0 +1,295 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+use InvalidArgumentException;
+
+class TSPropertyArray
+{
+ /**
+ * Represents that the TSPropertyArray data is valid.
+ */
+ const VALID_SIGNATURE = 'P';
+
+ /**
+ * The default values for the TSPropertyArray structure.
+ *
+ * @var array
+ */
+ const DEFAULTS = [
+ 'CtxCfgPresent' => 2953518677,
+ 'CtxWFProfilePath' => '',
+ 'CtxWFProfilePathW' => '',
+ 'CtxWFHomeDir' => '',
+ 'CtxWFHomeDirW' => '',
+ 'CtxWFHomeDirDrive' => '',
+ 'CtxWFHomeDirDriveW' => '',
+ 'CtxShadow' => 1,
+ 'CtxMaxDisconnectionTime' => 0,
+ 'CtxMaxConnectionTime' => 0,
+ 'CtxMaxIdleTime' => 0,
+ 'CtxWorkDirectory' => '',
+ 'CtxWorkDirectoryW' => '',
+ 'CtxCfgFlags1' => 2418077696,
+ 'CtxInitialProgram' => '',
+ 'CtxInitialProgramW' => '',
+ ];
+
+ /**
+ * @var string The default data that occurs before the TSPropertyArray (CtxCfgPresent with a bunch of spaces...?)
+ */
+ protected $defaultPreBinary = '43747843666750726573656e742020202020202020202020202020202020202020202020202020202020202020202020';
+
+ /**
+ * @var TSProperty[]
+ */
+ protected $tsProperty = [];
+
+ /**
+ * @var string
+ */
+ protected $signature = self::VALID_SIGNATURE;
+
+ /**
+ * Binary data that occurs before the TSPropertyArray data in userParameters.
+ *
+ * @var string
+ */
+ protected $preBinary = '';
+
+ /**
+ * Binary data that occurs after the TSPropertyArray data in userParameters.
+ *
+ * @var string
+ */
+ protected $postBinary = '';
+
+ /**
+ * Construct in one of the following ways:.
+ *
+ * - Pass an array of TSProperty key => value pairs (See DEFAULTS constant).
+ * - Pass the userParameters binary value. The object representation of that will be decoded and constructed.
+ * - Pass nothing and a default set of TSProperty key => value pairs will be used (See DEFAULTS constant).
+ *
+ * @param mixed $tsPropertyArray
+ */
+ public function __construct($tsPropertyArray = null)
+ {
+ $this->preBinary = hex2bin($this->defaultPreBinary);
+
+ if (is_null($tsPropertyArray) || is_array($tsPropertyArray)) {
+ $tsPropertyArray = $tsPropertyArray ?: self::DEFAULTS;
+
+ foreach ($tsPropertyArray as $key => $value) {
+ $tsProperty = new TSProperty();
+
+ $this->tsProperty[$key] = $tsProperty->setName($key)->setValue($value);
+ }
+ } else {
+ $this->decodeUserParameters($tsPropertyArray);
+ }
+ }
+
+ /**
+ * Check if a specific TSProperty exists by its property name.
+ *
+ * @param string $propName
+ *
+ * @return bool
+ */
+ public function has($propName)
+ {
+ return array_key_exists(strtolower($propName), array_change_key_case($this->tsProperty));
+ }
+
+ /**
+ * Get a TSProperty object by its property name (ie. CtxWFProfilePath).
+ *
+ * @param string $propName
+ *
+ * @return TSProperty
+ */
+ public function get($propName)
+ {
+ $this->validateProp($propName);
+
+ return $this->getTsPropObj($propName);
+ }
+
+ /**
+ * Add a TSProperty object. If it already exists, it will be overwritten.
+ *
+ * @param TSProperty $tsProperty
+ *
+ * @return $this
+ */
+ public function add(TSProperty $tsProperty)
+ {
+ $this->tsProperty[$tsProperty->getName()] = $tsProperty;
+
+ return $this;
+ }
+
+ /**
+ * Remove a TSProperty by its property name (ie. CtxMinEncryptionLevel).
+ *
+ * @param string $propName
+ *
+ * @return $this
+ */
+ public function remove($propName)
+ {
+ foreach (array_keys($this->tsProperty) as $property) {
+ if (strtolower($propName) == strtolower($property)) {
+ unset($this->tsProperty[$property]);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the value for a specific TSProperty by its name.
+ *
+ * @param string $propName
+ * @param mixed $propValue
+ *
+ * @return $this
+ */
+ public function set($propName, $propValue)
+ {
+ $this->validateProp($propName);
+
+ $this->getTsPropObj($propName)->setValue($propValue);
+
+ return $this;
+ }
+
+ /**
+ * Get the full binary representation of the userParameters containing the TSPropertyArray data.
+ *
+ * @return string
+ */
+ public function toBinary()
+ {
+ $binary = $this->preBinary;
+
+ $binary .= hex2bin(str_pad(dechex(MbString::ord($this->signature)), 2, 0, STR_PAD_LEFT));
+
+ $binary .= hex2bin(str_pad(dechex(count($this->tsProperty)), 2, 0, STR_PAD_LEFT));
+
+ foreach ($this->tsProperty as $tsProperty) {
+ $binary .= $tsProperty->toBinary();
+ }
+
+ return $binary.$this->postBinary;
+ }
+
+ /**
+ * Get a simple associative array containing of all TSProperty names and values.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $userParameters = [];
+
+ foreach ($this->tsProperty as $property => $tsPropObj) {
+ $userParameters[$property] = $tsPropObj->getValue();
+ }
+
+ return $userParameters;
+ }
+
+ /**
+ * Get all TSProperty objects.
+ *
+ * @return TSProperty[]
+ */
+ public function getTSProperties()
+ {
+ return $this->tsProperty;
+ }
+
+ /**
+ * Validates that the given property name exists.
+ *
+ * @param string $propName
+ */
+ protected function validateProp($propName)
+ {
+ if (! $this->has($propName)) {
+ throw new InvalidArgumentException(sprintf('TSProperty for "%s" does not exist.', $propName));
+ }
+ }
+
+ /**
+ * @param string $propName
+ *
+ * @return TSProperty
+ */
+ protected function getTsPropObj($propName)
+ {
+ return array_change_key_case($this->tsProperty)[strtolower($propName)];
+ }
+
+ /**
+ * Get an associative array with all of the userParameters property names and values.
+ *
+ * @param string $userParameters
+ *
+ * @return void
+ */
+ protected function decodeUserParameters($userParameters)
+ {
+ $userParameters = bin2hex($userParameters);
+
+ // Save the 96-byte array of reserved data, so as to not ruin anything that may be stored there.
+ $this->preBinary = hex2bin(substr($userParameters, 0, 96));
+ // The signature is a 2-byte unicode character at the front
+ $this->signature = MbString::chr(hexdec(substr($userParameters, 96, 2)));
+ // This asserts the validity of the tsPropertyArray data. For some reason 'P' means valid...
+ if ($this->signature != self::VALID_SIGNATURE) {
+ throw new InvalidArgumentException('Invalid TSPropertyArray data');
+ }
+
+ // The property count is a 2-byte unsigned integer indicating the number of elements for the tsPropertyArray
+ // It starts at position 98. The actual variable data begins at position 100.
+ $length = $this->addTSPropData(substr($userParameters, 100), hexdec(substr($userParameters, 98, 2)));
+
+ // Reserved data length + (count and sig length == 4) + the added lengths of the TSPropertyArray
+ // This saves anything after that variable TSPropertyArray data, so as to not squash anything stored there
+ if (strlen($userParameters) > (96 + 4 + $length)) {
+ $this->postBinary = hex2bin(substr($userParameters, (96 + 4 + $length)));
+ }
+ }
+
+ /**
+ * Given the start of TSPropertyArray hex data, and the count for the number
+ * of TSProperty structures in contains, parse and split out the
+ * individual TSProperty structures. Return the full length
+ * of the TSPropertyArray data.
+ *
+ * @param string $tsPropertyArray
+ * @param int $tsPropCount
+ *
+ * @return int The length of the data in the TSPropertyArray
+ */
+ protected function addTSPropData($tsPropertyArray, $tsPropCount)
+ {
+ $length = 0;
+
+ for ($i = 0; $i < $tsPropCount; $i++) {
+ // Prop length = name length + value length + type length + the space for the length data.
+ $propLength = hexdec(substr($tsPropertyArray, $length, 2)) + (hexdec(substr($tsPropertyArray, $length + 2, 2)) * 3) + 6;
+
+ $tsProperty = new TSProperty(hex2bin(substr($tsPropertyArray, $length, $propLength)));
+
+ $this->tsProperty[$tsProperty->getName()] = $tsProperty;
+
+ $length += $propLength;
+ }
+
+ return $length;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Timestamp.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Timestamp.php
new file mode 100644
index 0000000..abd656c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Timestamp.php
@@ -0,0 +1,244 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+use Carbon\Carbon;
+use Carbon\CarbonInterface;
+use DateTime;
+use LdapRecord\LdapRecordException;
+use LdapRecord\Utilities;
+
+class Timestamp
+{
+ /**
+ * The current timestamp type.
+ *
+ * @var string
+ */
+ protected $type;
+
+ /**
+ * The available timestamp types.
+ *
+ * @var array
+ */
+ protected $types = [
+ 'ldap',
+ 'windows',
+ 'windows-int',
+ ];
+
+ /**
+ * Constructor.
+ *
+ * @param string $type
+ *
+ * @throws LdapRecordException
+ */
+ public function __construct($type)
+ {
+ $this->setType($type);
+ }
+
+ /**
+ * Set the type of timestamp to convert from / to.
+ *
+ * @param string $type
+ *
+ * @throws LdapRecordException
+ */
+ public function setType($type)
+ {
+ if (! in_array($type, $this->types)) {
+ throw new LdapRecordException("Unrecognized LDAP date type [$type]");
+ }
+
+ $this->type = $type;
+ }
+
+ /**
+ * Converts the value to an LDAP date string.
+ *
+ * @param mixed $value
+ *
+ * @throws LdapRecordException
+ *
+ * @return float|string
+ */
+ public function fromDateTime($value)
+ {
+ $value = is_array($value) ? reset($value) : $value;
+
+ // If the value is being converted to a windows integer format but it
+ // is already in that format, we will simply return the value back.
+ if ($this->type == 'windows-int' && $this->valueIsWindowsIntegerType($value)) {
+ return $value;
+ }
+ // If the value is numeric, we will assume it's a UNIX timestamp.
+ elseif (is_numeric($value)) {
+ $value = Carbon::createFromTimestamp($value);
+ }
+ // If a string is given, we will pass it into a new carbon instance.
+ elseif (is_string($value)) {
+ $value = Carbon::parse($value);
+ }
+ // If a date object is given, we will convert it to a carbon instance.
+ elseif ($value instanceof DateTime) {
+ $value = Carbon::instance($value);
+ }
+
+ switch ($this->type) {
+ case 'ldap':
+ $value = $this->convertDateTimeToLdapTime($value);
+ break;
+ case 'windows':
+ $value = $this->convertDateTimeToWindows($value);
+ break;
+ case 'windows-int':
+ $value = $this->convertDateTimeToWindowsInteger($value);
+ break;
+ default:
+ throw new LdapRecordException("Unrecognized date type [{$this->type}]");
+ }
+
+ return $value;
+ }
+
+ /**
+ * Determine if the value given is in Windows Integer (NTFS Filetime) format.
+ *
+ * @param int|string $value
+ *
+ * @return bool
+ */
+ protected function valueIsWindowsIntegerType($value)
+ {
+ return is_numeric($value) && strlen((string) $value) === 18;
+ }
+
+ /**
+ * Converts the LDAP timestamp value to a Carbon instance.
+ *
+ * @param mixed $value
+ *
+ * @throws LdapRecordException
+ *
+ * @return Carbon|false
+ */
+ public function toDateTime($value)
+ {
+ $value = is_array($value) ? reset($value) : $value;
+
+ if ($value instanceof CarbonInterface || $value instanceof DateTime) {
+ return Carbon::instance($value);
+ }
+
+ switch ($this->type) {
+ case 'ldap':
+ $value = $this->convertLdapTimeToDateTime($value);
+ break;
+ case 'windows':
+ $value = $this->convertWindowsTimeToDateTime($value);
+ break;
+ case 'windows-int':
+ $value = $this->convertWindowsIntegerTimeToDateTime($value);
+ break;
+ default:
+ throw new LdapRecordException("Unrecognized date type [{$this->type}]");
+ }
+
+ return $value instanceof DateTime ? Carbon::instance($value) : $value;
+ }
+
+ /**
+ * Converts standard LDAP timestamps to a date time object.
+ *
+ * @param string $value
+ *
+ * @return DateTime|bool
+ */
+ protected function convertLdapTimeToDateTime($value)
+ {
+ return DateTime::createFromFormat(
+ strpos($value, 'Z') !== false ? 'YmdHis\Z' : 'YmdHisT',
+ $value
+ );
+ }
+
+ /**
+ * Converts date objects to a standard LDAP timestamp.
+ *
+ * @param DateTime $date
+ *
+ * @return string
+ */
+ protected function convertDateTimeToLdapTime(DateTime $date)
+ {
+ return $date->format(
+ $date->getOffset() == 0 ? 'YmdHis\Z' : 'YmdHisO'
+ );
+ }
+
+ /**
+ * Converts standard windows timestamps to a date time object.
+ *
+ * @param string $value
+ *
+ * @return DateTime|bool
+ */
+ protected function convertWindowsTimeToDateTime($value)
+ {
+ return DateTime::createFromFormat(
+ strpos($value, '0Z') !== false ? 'YmdHis.0\Z' : 'YmdHis.0T',
+ $value
+ );
+ }
+
+ /**
+ * Converts date objects to a windows timestamp.
+ *
+ * @param DateTime $date
+ *
+ * @return string
+ */
+ protected function convertDateTimeToWindows(DateTime $date)
+ {
+ return $date->format(
+ $date->getOffset() == 0 ? 'YmdHis.0\Z' : 'YmdHis.0O'
+ );
+ }
+
+ /**
+ * Converts standard windows integer dates to a date time object.
+ *
+ * @param int $value
+ *
+ * @throws \Exception
+ *
+ * @return DateTime|bool
+ */
+ protected function convertWindowsIntegerTimeToDateTime($value)
+ {
+ // ActiveDirectory dates that contain integers may return
+ // "0" when they are not set. We will validate that here.
+ if (! $value) {
+ return false;
+ }
+
+ return (new DateTime())->setTimestamp(
+ Utilities::convertWindowsTimeToUnixTime($value)
+ );
+ }
+
+ /**
+ * Converts date objects to a windows integer timestamp.
+ *
+ * @param DateTime $date
+ *
+ * @return float
+ */
+ protected function convertDateTimeToWindowsInteger(DateTime $date)
+ {
+ return Utilities::convertUnixTimeToWindowsTime($date->getTimestamp());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/BatchModification.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/BatchModification.php
new file mode 100644
index 0000000..37f0e87
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/BatchModification.php
@@ -0,0 +1,307 @@
+<?php
+
+namespace LdapRecord\Models;
+
+use InvalidArgumentException;
+
+class BatchModification
+{
+ use DetectsResetIntegers;
+
+ /**
+ * The array keys to be used in batch modifications.
+ */
+ const KEY_ATTRIB = 'attrib';
+ const KEY_MODTYPE = 'modtype';
+ const KEY_VALUES = 'values';
+
+ /**
+ * The attribute of the modification.
+ *
+ * @var string|null
+ */
+ protected $attribute;
+
+ /**
+ * The original value of the attribute before modification.
+ *
+ * @var array
+ */
+ protected $original = [];
+
+ /**
+ * The values of the modification.
+ *
+ * @var array
+ */
+ protected $values = [];
+
+ /**
+ * The modtype integer of the batch modification.
+ *
+ * @var int|null
+ */
+ protected $type;
+
+ /**
+ * Constructor.
+ *
+ * @param string|null $attribute
+ * @param string|int|null $type
+ * @param array $values
+ */
+ public function __construct($attribute = null, $type = null, array $values = [])
+ {
+ $this->setAttribute($attribute)
+ ->setType($type)
+ ->setValues($values);
+ }
+
+ /**
+ * Set the original value of the attribute before modification.
+ *
+ * @param array|string $original
+ *
+ * @return $this
+ */
+ public function setOriginal($original = [])
+ {
+ $this->original = $this->normalizeAttributeValues($original);
+
+ return $this;
+ }
+
+ /**
+ * Returns the original value of the attribute before modification.
+ *
+ * @return array
+ */
+ public function getOriginal()
+ {
+ return $this->original;
+ }
+
+ /**
+ * Set the attribute of the modification.
+ *
+ * @param string $attribute
+ *
+ * @return $this
+ */
+ public function setAttribute($attribute)
+ {
+ $this->attribute = $attribute;
+
+ return $this;
+ }
+
+ /**
+ * Returns the attribute of the modification.
+ *
+ * @return string
+ */
+ public function getAttribute()
+ {
+ return $this->attribute;
+ }
+
+ /**
+ * Set the values of the modification.
+ *
+ * @param array $values
+ *
+ * @return $this
+ */
+ public function setValues(array $values = [])
+ {
+ // Null and empty values must also not be added to a batch
+ // modification. Passing null or empty values will result
+ // in an exception when trying to save the modification.
+ $this->values = array_filter($this->normalizeAttributeValues($values), function ($value) {
+ return is_numeric($value) && $this->valueIsResetInteger((int) $value) ?: ! empty($value);
+ });
+
+ return $this;
+ }
+
+ /**
+ * Normalize all of the attribute values.
+ *
+ * @param array|string $values
+ *
+ * @return array
+ */
+ protected function normalizeAttributeValues($values = [])
+ {
+ // We must convert all of the values to strings. Only strings can
+ // be used in batch modifications, otherwise we will we will
+ // receive an LDAP exception while attempting to save.
+ return array_map('strval', (array) $values);
+ }
+
+ /**
+ * Returns the values of the modification.
+ *
+ * @return array
+ */
+ public function getValues()
+ {
+ return $this->values;
+ }
+
+ /**
+ * Set the type of the modification.
+ *
+ * @param int|null $type
+ *
+ * @return $this
+ */
+ public function setType($type = null)
+ {
+ if (is_null($type)) {
+ return $this;
+ }
+
+ if (! $this->isValidType($type)) {
+ throw new InvalidArgumentException('Given batch modification type is invalid.');
+ }
+
+ $this->type = $type;
+
+ return $this;
+ }
+
+ /**
+ * Returns the type of the modification.
+ *
+ * @return int
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Determines if the batch modification is valid in its current state.
+ *
+ * @return bool
+ */
+ public function isValid()
+ {
+ return ! is_null($this->get());
+ }
+
+ /**
+ * Builds the type of modification automatically
+ * based on the current and original values.
+ *
+ * @return $this
+ */
+ public function build()
+ {
+ switch (true) {
+ case empty($this->original) && empty($this->values):
+ return $this;
+ case ! empty($this->original) && empty($this->values):
+ return $this->setType(LDAP_MODIFY_BATCH_REMOVE_ALL);
+ case empty($this->original) && ! empty($this->values):
+ return $this->setType(LDAP_MODIFY_BATCH_ADD);
+ default:
+ return $this->determineBatchTypeFromOriginal();
+ }
+ }
+
+ /**
+ * Determine the batch modification type from the original values.
+ *
+ * @return $this
+ */
+ protected function determineBatchTypeFromOriginal()
+ {
+ $added = $this->getAddedValues();
+ $removed = $this->getRemovedValues();
+
+ switch (true) {
+ case ! empty($added) && ! empty($removed):
+ return $this->setType(LDAP_MODIFY_BATCH_REPLACE);
+ case ! empty($added):
+ return $this->setValues($added)->setType(LDAP_MODIFY_BATCH_ADD);
+ case ! empty($removed):
+ return $this->setValues($removed)->setType(LDAP_MODIFY_BATCH_REMOVE);
+ default:
+ return $this;
+ }
+ }
+
+ /**
+ * Get the values that were added to the attribute.
+ *
+ * @return array
+ */
+ protected function getAddedValues()
+ {
+ return array_values(
+ array_diff($this->values, $this->original)
+ );
+ }
+
+ /**
+ * Get the values that were removed from the attribute.
+ *
+ * @return array
+ */
+ protected function getRemovedValues()
+ {
+ return array_values(
+ array_diff($this->original, $this->values)
+ );
+ }
+
+ /**
+ * Returns the built batch modification array.
+ *
+ * @return array|null
+ */
+ public function get()
+ {
+ switch ($this->type) {
+ case LDAP_MODIFY_BATCH_REMOVE_ALL:
+ // A values key cannot be provided when
+ // a remove all type is selected.
+ return [
+ static::KEY_ATTRIB => $this->attribute,
+ static::KEY_MODTYPE => $this->type,
+ ];
+ case LDAP_MODIFY_BATCH_REMOVE:
+ // Fallthrough.
+ case LDAP_MODIFY_BATCH_ADD:
+ // Fallthrough.
+ case LDAP_MODIFY_BATCH_REPLACE:
+ return [
+ static::KEY_ATTRIB => $this->attribute,
+ static::KEY_MODTYPE => $this->type,
+ static::KEY_VALUES => $this->values,
+ ];
+ default:
+ // If the modtype isn't recognized, we'll return null.
+ return;
+ }
+ }
+
+ /**
+ * Determines if the given modtype is valid.
+ *
+ * @param int $type
+ *
+ * @return bool
+ */
+ protected function isValidType($type)
+ {
+ return in_array($type, [
+ LDAP_MODIFY_BATCH_REMOVE_ALL,
+ LDAP_MODIFY_BATCH_REMOVE,
+ LDAP_MODIFY_BATCH_REPLACE,
+ LDAP_MODIFY_BATCH_ADD,
+ ]);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Collection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Collection.php
new file mode 100644
index 0000000..850167b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Collection.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace LdapRecord\Models;
+
+use Closure;
+use LdapRecord\Models\Attributes\DistinguishedName;
+use LdapRecord\Query\Collection as QueryCollection;
+use LdapRecord\Support\Arr;
+
+class Collection extends QueryCollection
+{
+ /**
+ * Determine if the collection contains all of the given models, or any models.
+ *
+ * @param mixed $models
+ *
+ * @return bool
+ */
+ public function exists($models = null)
+ {
+ $models = $this->getArrayableModels($models);
+
+ // If any arguments were given and the result set is
+ // empty, we can simply return false here. We can't
+ // verify the existence of models without results.
+ if (func_num_args() > 0 && empty(array_filter($models))) {
+ return false;
+ }
+
+ if (! $models) {
+ return parent::isNotEmpty();
+ }
+
+ foreach ($models as $model) {
+ $exists = parent::contains(function (Model $related) use ($model) {
+ return $this->compareModelWithRelated($model, $related);
+ });
+
+ if (! $exists) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Determine if any of the given models are contained in the collection.
+ *
+ * @param mixed $key
+ * @param mixed $operator
+ * @param mixed $value
+ *
+ * @return bool
+ */
+ public function contains($key, $operator = null, $value = null)
+ {
+ if (func_num_args() > 1 || $key instanceof Closure) {
+ // If we are supplied with more than one argument, or
+ // we were passed a closure, we will utilize the
+ // parents contains method, for compatibility.
+ return parent::contains($key, $operator, $value);
+ }
+
+ foreach ($this->getArrayableModels($key) as $model) {
+ $exists = parent::contains(function (Model $related) use ($model) {
+ return $this->compareModelWithRelated($model, $related);
+ });
+
+ if ($exists) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the provided models as an array.
+ *
+ * @param mixed $models
+ *
+ * @return array
+ */
+ protected function getArrayableModels($models = null)
+ {
+ return $models instanceof QueryCollection
+ ? $models->toArray()
+ : Arr::wrap($models);
+ }
+
+ /**
+ * Compare the related model with the given.
+ *
+ * @param Model|string $model
+ * @param Model $related
+ *
+ * @return bool
+ */
+ protected function compareModelWithRelated($model, $related)
+ {
+ if (is_string($model)) {
+ return $this->isValidDn($model)
+ ? $related->getDn() == $model
+ : $related->getName() == $model;
+ }
+
+ return $related->is($model);
+ }
+
+ /**
+ * Determine if the given string is a valid distinguished name.
+ *
+ * @param string $dn
+ *
+ * @return bool
+ */
+ protected function isValidDn($dn)
+ {
+ return ! empty((new DistinguishedName($dn))->components());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/CanAuthenticate.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/CanAuthenticate.php
new file mode 100644
index 0000000..f287454
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/CanAuthenticate.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace LdapRecord\Models\Concerns;
+
+trait CanAuthenticate
+{
+ /**
+ * Get the name of the unique identifier for the user.
+ *
+ * @return string
+ */
+ public function getAuthIdentifierName()
+ {
+ return $this->guidKey;
+ }
+
+ /**
+ * Get the unique identifier for the user.
+ *
+ * @return mixed
+ */
+ public function getAuthIdentifier()
+ {
+ return $this->getConvertedGuid();
+ }
+
+ /**
+ * Get the password for the user.
+ *
+ * @return string
+ */
+ public function getAuthPassword()
+ {
+ }
+
+ /**
+ * Get the token value for the "remember me" session.
+ *
+ * @return string
+ */
+ public function getRememberToken()
+ {
+ }
+
+ /**
+ * Set the token value for the "remember me" session.
+ *
+ * @param string $value
+ *
+ * @return void
+ */
+ public function setRememberToken($value)
+ {
+ }
+
+ /**
+ * Get the column name for the "remember me" token.
+ *
+ * @return string
+ */
+ public function getRememberTokenName()
+ {
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasAttributes.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasAttributes.php
new file mode 100644
index 0000000..20fcec0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasAttributes.php
@@ -0,0 +1,1106 @@
+<?php
+
+namespace LdapRecord\Models\Concerns;
+
+use Carbon\Carbon;
+use DateTimeInterface;
+use Exception;
+use LdapRecord\LdapRecordException;
+use LdapRecord\Models\Attributes\MbString;
+use LdapRecord\Models\Attributes\Timestamp;
+use LdapRecord\Models\DetectsResetIntegers;
+use LdapRecord\Support\Arr;
+
+trait HasAttributes
+{
+ use DetectsResetIntegers;
+
+ /**
+ * The models original attributes.
+ *
+ * @var array
+ */
+ protected $original = [];
+
+ /**
+ * The models attributes.
+ *
+ * @var array
+ */
+ protected $attributes = [];
+
+ /**
+ * The attributes that should be mutated to dates.
+ *
+ * @var array
+ */
+ protected $dates = [];
+
+ /**
+ * The attributes that should be cast to their native types.
+ *
+ * @var array
+ */
+ protected $casts = [];
+
+ /**
+ * The accessors to append to the model's array form.
+ *
+ * @var array
+ */
+ protected $appends = [];
+
+ /**
+ * The format that dates must be output to for serialization.
+ *
+ * @var string
+ */
+ protected $dateFormat;
+
+ /**
+ * The default attributes that should be mutated to dates.
+ *
+ * @var array
+ */
+ protected $defaultDates = [
+ 'createtimestamp' => 'ldap',
+ 'modifytimestamp' => 'ldap',
+ ];
+
+ /**
+ * The cache of the mutated attributes for each class.
+ *
+ * @var array
+ */
+ protected static $mutatorCache = [];
+
+ /**
+ * Convert the model's attributes to an array.
+ *
+ * @return array
+ */
+ public function attributesToArray()
+ {
+ // Here we will replace our LDAP formatted dates with
+ // properly formatted ones, so dates do not need to
+ // be converted manually after being returned.
+ $attributes = $this->addDateAttributesToArray(
+ $attributes = $this->getArrayableAttributes()
+ );
+
+ $attributes = $this->addMutatedAttributesToArray(
+ $attributes,
+ $this->getMutatedAttributes()
+ );
+
+ // Before we go ahead and encode each value, we'll attempt
+ // converting any necessary attribute values to ensure
+ // they can be encoded, such as GUIDs and SIDs.
+ $attributes = $this->convertAttributesForJson($attributes);
+
+ // Here we will grab all of the appended, calculated attributes to this model
+ // as these attributes are not really in the attributes array, but are run
+ // when we need to array or JSON the model for convenience to the coder.
+ foreach ($this->getArrayableAppends() as $key) {
+ $attributes[$key] = $this->mutateAttributeForArray($key, null);
+ }
+
+ // Now we will go through each attribute to make sure it is
+ // properly encoded. If attributes aren't in UTF-8, we will
+ // encounter JSON encoding errors upon model serialization.
+ return $this->encodeAttributes($attributes);
+ }
+
+ /**
+ * Add the date attributes to the attributes array.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+ protected function addDateAttributesToArray(array $attributes)
+ {
+ foreach ($this->getDates() as $attribute => $type) {
+ if (! isset($attributes[$attribute])) {
+ continue;
+ }
+
+ $date = $this->asDateTime($attributes[$attribute], $type);
+
+ $attributes[$attribute] = $date instanceof Carbon
+ ? Arr::wrap($this->serializeDate($date))
+ : $attributes[$attribute];
+ }
+
+ return $attributes;
+ }
+
+ /**
+ * Prepare a date for array / JSON serialization.
+ *
+ * @param DateTimeInterface $date
+ *
+ * @return string
+ */
+ protected function serializeDate(DateTimeInterface $date)
+ {
+ return $date->format($this->getDateFormat());
+ }
+
+ /**
+ * Recursively UTF-8 encode the given attributes.
+ *
+ * @return array
+ */
+ public function encodeAttributes($attributes)
+ {
+ array_walk_recursive($attributes, function (&$value) {
+ $value = $this->encodeValue($value);
+ });
+
+ return $attributes;
+ }
+
+ /**
+ * Encode the given value for proper serialization.
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ protected function encodeValue($value)
+ {
+ // If we are able to detect the encoding, we will
+ // encode only the attributes that need to be,
+ // so that we do not double encode values.
+ return MbString::isLoaded() && MbString::isUtf8($value) ? $value : utf8_encode($value);
+ }
+
+ /**
+ * Add the mutated attributes to the attributes array.
+ *
+ * @param array $attributes
+ * @param array $mutatedAttributes
+ *
+ * @return array
+ */
+ protected function addMutatedAttributesToArray(array $attributes, array $mutatedAttributes)
+ {
+ foreach ($mutatedAttributes as $key) {
+ // We want to spin through all the mutated attributes for this model and call
+ // the mutator for the attribute. We cache off every mutated attributes so
+ // we don't have to constantly check on attributes that actually change.
+ if (! Arr::exists($attributes, $key)) {
+ continue;
+ }
+
+ // Next, we will call the mutator for this attribute so that we can get these
+ // mutated attribute's actual values. After we finish mutating each of the
+ // attributes we will return this final array of the mutated attributes.
+ $attributes[$key] = $this->mutateAttributeForArray(
+ $key,
+ $attributes[$key]
+ );
+ }
+
+ return $attributes;
+ }
+
+ /**
+ * Set the model's original attributes with the model's current attributes.
+ *
+ * @return $this
+ */
+ public function syncOriginal()
+ {
+ $this->original = $this->attributes;
+
+ return $this;
+ }
+
+ /**
+ * Fills the entry with the supplied attributes.
+ *
+ * @param array $attributes
+ *
+ * @return $this
+ */
+ public function fill(array $attributes = [])
+ {
+ foreach ($attributes as $key => $value) {
+ $this->setAttribute($key, $value);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the models attribute by its key.
+ *
+ * @param int|string $key
+ *
+ * @return mixed
+ */
+ public function getAttribute($key)
+ {
+ if (! $key) {
+ return;
+ }
+
+ return $this->getAttributeValue($key);
+ }
+
+ /**
+ * Get an attributes value.
+ *
+ * @param string $key
+ *
+ * @return mixed
+ */
+ public function getAttributeValue($key)
+ {
+ $key = $this->normalizeAttributeKey($key);
+ $value = $this->getAttributeFromArray($key);
+
+ if ($this->hasGetMutator($key)) {
+ return $this->getMutatedAttributeValue($key, $value);
+ }
+
+ if ($this->isDateAttribute($key) && ! is_null($value)) {
+ return $this->asDateTime(Arr::first($value), $this->getDates()[$key]);
+ }
+
+ if ($this->isCastedAttribute($key) && ! is_null($value)) {
+ return $this->castAttribute($key, $value);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Determine if the given attribute is a date.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function isDateAttribute($key)
+ {
+ return array_key_exists($key, $this->getDates());
+ }
+
+ /**
+ * Get the attributes that should be mutated to dates.
+ *
+ * @return array
+ */
+ public function getDates()
+ {
+ // Since array string keys can be unique depending
+ // on casing differences, we need to normalize the
+ // array key case so they are merged properly.
+ return array_merge(
+ array_change_key_case($this->defaultDates, CASE_LOWER),
+ array_change_key_case($this->dates, CASE_LOWER)
+ );
+ }
+
+ /**
+ * Convert the given date value to an LDAP compatible value.
+ *
+ * @param string $type
+ * @param mixed $value
+ *
+ * @throws LdapRecordException
+ *
+ * @return float|string
+ */
+ public function fromDateTime($type, $value)
+ {
+ return (new Timestamp($type))->fromDateTime($value);
+ }
+
+ /**
+ * Convert the given LDAP date value to a Carbon instance.
+ *
+ * @param mixed $value
+ * @param string $type
+ *
+ * @throws LdapRecordException
+ *
+ * @return Carbon|false
+ */
+ public function asDateTime($value, $type)
+ {
+ return (new Timestamp($type))->toDateTime($value);
+ }
+
+ /**
+ * Determine whether an attribute should be cast to a native type.
+ *
+ * @param string $key
+ * @param array|string|null $types
+ *
+ * @return bool
+ */
+ public function hasCast($key, $types = null)
+ {
+ if (array_key_exists($key, $this->getCasts())) {
+ return $types ? in_array($this->getCastType($key), (array) $types, true) : true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the attributes that should be cast to their native types.
+ *
+ * @return array
+ */
+ protected function getCasts()
+ {
+ return array_change_key_case($this->casts, CASE_LOWER);
+ }
+
+ /**
+ * Determine whether a value is JSON castable for inbound manipulation.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ protected function isJsonCastable($key)
+ {
+ return $this->hasCast($key, ['array', 'json', 'object', 'collection']);
+ }
+
+ /**
+ * Get the type of cast for a model attribute.
+ *
+ * @param string $key
+ *
+ * @return string
+ */
+ protected function getCastType($key)
+ {
+ if ($this->isDecimalCast($this->getCasts()[$key])) {
+ return 'decimal';
+ }
+
+ if ($this->isDateTimeCast($this->getCasts()[$key])) {
+ return 'datetime';
+ }
+
+ return trim(strtolower($this->getCasts()[$key]));
+ }
+
+ /**
+ * Determine if the cast is a decimal.
+ *
+ * @param string $cast
+ *
+ * @return bool
+ */
+ protected function isDecimalCast($cast)
+ {
+ return strncmp($cast, 'decimal:', 8) === 0;
+ }
+
+ /**
+ * Determine if the cast is a datetime.
+ *
+ * @param string $cast
+ *
+ * @return bool
+ */
+ protected function isDateTimeCast($cast)
+ {
+ return strncmp($cast, 'datetime:', 8) === 0;
+ }
+
+ /**
+ * Determine if the given attribute must be casted.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ protected function isCastedAttribute($key)
+ {
+ return array_key_exists($key, array_change_key_case($this->casts, CASE_LOWER));
+ }
+
+ /**
+ * Cast an attribute to a native PHP type.
+ *
+ * @param string $key
+ * @param array|null $value
+ *
+ * @return mixed
+ */
+ protected function castAttribute($key, $value)
+ {
+ $value = $this->castRequiresArrayValue($key) ? $value : Arr::first($value);
+
+ if (is_null($value)) {
+ return $value;
+ }
+
+ switch ($this->getCastType($key)) {
+ case 'int':
+ case 'integer':
+ return (int) $value;
+ case 'real':
+ case 'float':
+ case 'double':
+ return $this->fromFloat($value);
+ case 'decimal':
+ return $this->asDecimal($value, explode(':', $this->getCasts()[$key], 2)[1]);
+ case 'string':
+ return (string) $value;
+ case 'bool':
+ case 'boolean':
+ return $this->asBoolean($value);
+ case 'object':
+ return $this->fromJson($value, $asObject = true);
+ case 'array':
+ case 'json':
+ return $this->fromJson($value);
+ case 'collection':
+ return $this->newCollection($value);
+ case 'datetime':
+ return $this->asDateTime($value, explode(':', $this->getCasts()[$key], 2)[1]);
+ default:
+ return $value;
+ }
+ }
+
+ /**
+ * Determine if the cast type requires the first attribute value.
+ *
+ * @return bool
+ */
+ protected function castRequiresArrayValue($key)
+ {
+ return in_array($this->getCastType($key), ['collection']);
+ }
+
+ /**
+ * Cast the given attribute to JSON.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @return string
+ */
+ protected function castAttributeAsJson($key, $value)
+ {
+ $value = $this->asJson($value);
+
+ if ($value === false) {
+ $class = get_class($this);
+ $message = json_last_error_msg();
+
+ throw new Exception("Unable to encode attribute [{$key}] for model [{$class}] to JSON: {$message}.");
+ }
+
+ return $value;
+ }
+
+ /**
+ * Convert the model to its JSON representation.
+ *
+ * @return string
+ */
+ public function toJson()
+ {
+ return json_encode($this);
+ }
+
+ /**
+ * Encode the given value as JSON.
+ *
+ * @param mixed $value
+ *
+ * @return string
+ */
+ protected function asJson($value)
+ {
+ return json_encode($value);
+ }
+
+ /**
+ * Decode the given JSON back into an array or object.
+ *
+ * @param string $value
+ * @param bool $asObject
+ *
+ * @return mixed
+ */
+ public function fromJson($value, $asObject = false)
+ {
+ return json_decode($value, ! $asObject);
+ }
+
+ /**
+ * Decode the given float.
+ *
+ * @param mixed $value
+ *
+ * @return mixed
+ */
+ public function fromFloat($value)
+ {
+ switch ((string) $value) {
+ case 'Infinity':
+ return INF;
+ case '-Infinity':
+ return -INF;
+ case 'NaN':
+ return NAN;
+ default:
+ return (float) $value;
+ }
+ }
+
+ /**
+ * Cast the value to a boolean.
+ *
+ * @param mixed $value
+ *
+ * @return bool
+ */
+ protected function asBoolean($value)
+ {
+ $map = ['true' => true, 'false' => false];
+
+ return $map[strtolower($value)] ?? (bool) $value;
+ }
+
+ /**
+ * Cast a decimal value as a string.
+ *
+ * @param float $value
+ * @param int $decimals
+ *
+ * @return string
+ */
+ protected function asDecimal($value, $decimals)
+ {
+ return number_format($value, $decimals, '.', '');
+ }
+
+ /**
+ * Get an attribute array of all arrayable attributes.
+ *
+ * @return array
+ */
+ protected function getArrayableAttributes()
+ {
+ return $this->getArrayableItems($this->attributes);
+ }
+
+ /**
+ * Get an attribute array of all arrayable values.
+ *
+ * @param array $values
+ *
+ * @return array
+ */
+ protected function getArrayableItems(array $values)
+ {
+ if (count($visible = $this->getVisible()) > 0) {
+ $values = array_intersect_key($values, array_flip($visible));
+ }
+
+ if (count($hidden = $this->getHidden()) > 0) {
+ $values = array_diff_key($values, array_flip($hidden));
+ }
+
+ return $values;
+ }
+
+ /**
+ * Get all of the appendable values that are arrayable.
+ *
+ * @return array
+ */
+ protected function getArrayableAppends()
+ {
+ if (empty($this->appends)) {
+ return [];
+ }
+
+ return $this->getArrayableItems(
+ array_combine($this->appends, $this->appends)
+ );
+ }
+
+ /**
+ * Get the format for date serialization.
+ *
+ * @return string
+ */
+ public function getDateFormat()
+ {
+ return $this->dateFormat ?: DateTimeInterface::ISO8601;
+ }
+
+ /**
+ * Set the date format used by the model for serialization.
+ *
+ * @param string $format
+ *
+ * @return $this
+ */
+ public function setDateFormat($format)
+ {
+ $this->dateFormat = $format;
+
+ return $this;
+ }
+
+ /**
+ * Get an attribute from the $attributes array.
+ *
+ * @param string $key
+ *
+ * @return mixed
+ */
+ protected function getAttributeFromArray($key)
+ {
+ return $this->getNormalizedAttributes()[$key] ?? null;
+ }
+
+ /**
+ * Get the attributes with their keys normalized.
+ *
+ * @return array
+ */
+ protected function getNormalizedAttributes()
+ {
+ return array_change_key_case($this->attributes, CASE_LOWER);
+ }
+
+ /**
+ * Returns the first attribute by the specified key.
+ *
+ * @param string $key
+ *
+ * @return mixed
+ */
+ public function getFirstAttribute($key)
+ {
+ return Arr::first(
+ Arr::wrap($this->getAttribute($key))
+ );
+ }
+
+ /**
+ * Returns all of the models attributes.
+ *
+ * @return array
+ */
+ public function getAttributes()
+ {
+ return $this->attributes;
+ }
+
+ /**
+ * Set an attribute value by the specified key and sub-key.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function setAttribute($key, $value)
+ {
+ $key = $this->normalizeAttributeKey($key);
+
+ if ($this->hasSetMutator($key)) {
+ return $this->setMutatedAttributeValue($key, $value);
+ } elseif (
+ $value &&
+ $this->isDateAttribute($key) &&
+ ! $this->valueIsResetInteger($value)
+ ) {
+ $value = $this->fromDateTime($this->getDates()[$key], $value);
+ }
+
+ if ($this->isJsonCastable($key) && ! is_null($value)) {
+ $value = $this->castAttributeAsJson($key, $value);
+ }
+
+ $this->attributes[$key] = Arr::wrap($value);
+
+ return $this;
+ }
+
+ /**
+ * Set the models first attribute value.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function setFirstAttribute($key, $value)
+ {
+ return $this->setAttribute($key, Arr::wrap($value));
+ }
+
+ /**
+ * Add a unique value to the given attribute.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function addAttributeValue($key, $value)
+ {
+ return $this->setAttribute($key, array_unique(
+ array_merge(
+ Arr::wrap($this->getAttribute($key)),
+ Arr::wrap($value)
+ )
+ ));
+ }
+
+ /**
+ * Determine if a get mutator exists for an attribute.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function hasGetMutator($key)
+ {
+ return method_exists($this, 'get'.$this->getMutatorMethodName($key).'Attribute');
+ }
+
+ /**
+ * Determine if a set mutator exists for an attribute.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function hasSetMutator($key)
+ {
+ return method_exists($this, 'set'.$this->getMutatorMethodName($key).'Attribute');
+ }
+
+ /**
+ * Set the value of an attribute using its mutator.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @return mixed
+ */
+ protected function setMutatedAttributeValue($key, $value)
+ {
+ return $this->{'set'.$this->getMutatorMethodName($key).'Attribute'}($value);
+ }
+
+ /**
+ * Get the value of an attribute using its mutator.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @return mixed
+ */
+ protected function getMutatedAttributeValue($key, $value)
+ {
+ return $this->{'get'.$this->getMutatorMethodName($key).'Attribute'}($value);
+ }
+
+ /**
+ * Get the mutator attribute method name.
+ *
+ * Hyphenated attributes will use pascal cased methods.
+ *
+ * @param string $key
+ *
+ * @return mixed
+ */
+ protected function getMutatorMethodName($key)
+ {
+ $key = ucwords(str_replace('-', ' ', $key));
+
+ return str_replace(' ', '', $key);
+ }
+
+ /**
+ * Get the value of an attribute using its mutator for array conversion.
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @return array
+ */
+ protected function mutateAttributeForArray($key, $value)
+ {
+ return Arr::wrap(
+ $this->getMutatedAttributeValue($key, $value)
+ );
+ }
+
+ /**
+ * Set the attributes property.
+ *
+ * Used when constructing an existing LDAP record.
+ *
+ * @param array $attributes
+ *
+ * @return $this
+ */
+ public function setRawAttributes(array $attributes = [])
+ {
+ // We will filter out those annoying 'count' keys
+ // returned with LDAP results and lowercase all
+ // root array keys to prevent any casing issues.
+ $raw = array_change_key_case($this->filterRawAttributes($attributes), CASE_LOWER);
+
+ // Before setting the models attributes, we will filter
+ // out the attributes that contain an integer key. LDAP
+ // search results will contain integer keys that have
+ // attribute names as values. We don't need these.
+ $this->attributes = array_filter($raw, function ($key) {
+ return ! is_int($key);
+ }, ARRAY_FILTER_USE_KEY);
+
+ // LDAP search results will contain the distinguished
+ // name inside of the `dn` key. We will retrieve this,
+ // and then set it on the model for accessibility.
+ if (Arr::exists($attributes, 'dn')) {
+ $this->dn = Arr::accessible($attributes['dn'])
+ ? Arr::first($attributes['dn'])
+ : $attributes['dn'];
+ }
+
+ $this->syncOriginal();
+
+ // Here we will set the exists attribute to true,
+ // since raw attributes are only set in the case
+ // of attributes being loaded by query results.
+ $this->exists = true;
+
+ return $this;
+ }
+
+ /**
+ * Filters the count key recursively from raw LDAP attributes.
+ *
+ * @param array $attributes
+ * @param array $keys
+ *
+ * @return array
+ */
+ public function filterRawAttributes(array $attributes = [], array $keys = ['count', 'dn'])
+ {
+ foreach ($keys as $key) {
+ unset($attributes[$key]);
+ }
+
+ foreach ($attributes as $key => $value) {
+ $attributes[$key] = is_array($value)
+ ? $this->filterRawAttributes($value, $keys)
+ : $value;
+ }
+
+ return $attributes;
+ }
+
+ /**
+ * Determine if the model has the given attribute.
+ *
+ * @param int|string $key
+ *
+ * @return bool
+ */
+ public function hasAttribute($key)
+ {
+ return [] !== ($this->attributes[$this->normalizeAttributeKey($key)] ?? []);
+ }
+
+ /**
+ * Returns the number of attributes.
+ *
+ * @return int
+ */
+ public function countAttributes()
+ {
+ return count($this->getAttributes());
+ }
+
+ /**
+ * Returns the models original attributes.
+ *
+ * @return array
+ */
+ public function getOriginal()
+ {
+ return $this->original;
+ }
+
+ /**
+ * Get the attributes that have been changed since last sync.
+ *
+ * @return array
+ */
+ public function getDirty()
+ {
+ $dirty = [];
+
+ foreach ($this->attributes as $key => $value) {
+ if ($this->isDirty($key)) {
+ // We need to reset the array using array_values due to
+ // LDAP requiring consecutive indices (0, 1, 2 etc.).
+ // We would receive an exception otherwise.
+ $dirty[$key] = array_values($value);
+ }
+ }
+
+ return $dirty;
+ }
+
+ /**
+ * Determine if the given attribute is dirty.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function isDirty($key)
+ {
+ return ! $this->originalIsEquivalent($key);
+ }
+
+ /**
+ * Get the accessors being appended to the models array form.
+ *
+ * @return array
+ */
+ public function getAppends()
+ {
+ return $this->appends;
+ }
+
+ /**
+ * Set the accessors to append to model arrays.
+ *
+ * @param array $appends
+ *
+ * @return $this
+ */
+ public function setAppends(array $appends)
+ {
+ $this->appends = $appends;
+
+ return $this;
+ }
+
+ /**
+ * Return whether the accessor attribute has been appended.
+ *
+ * @param string $attribute
+ *
+ * @return bool
+ */
+ public function hasAppended($attribute)
+ {
+ return in_array($attribute, $this->appends);
+ }
+
+ /**
+ * Returns a normalized attribute key.
+ *
+ * @param string $key
+ *
+ * @return string
+ */
+ public function normalizeAttributeKey($key)
+ {
+ // Since LDAP supports hyphens in attribute names,
+ // we'll convert attributes being retrieved by
+ // underscores into hyphens for convenience.
+ return strtolower(
+ str_replace('_', '-', $key)
+ );
+ }
+
+ /**
+ * Determine if the new and old values for a given key are equivalent.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ protected function originalIsEquivalent($key)
+ {
+ if (! array_key_exists($key, $this->original)) {
+ return false;
+ }
+
+ $current = $this->attributes[$key];
+ $original = $this->original[$key];
+
+ if ($current === $original) {
+ return true;
+ }
+
+ return is_numeric($current) &&
+ is_numeric($original) &&
+ strcmp((string) $current, (string) $original) === 0;
+ }
+
+ /**
+ * Get the mutated attributes for a given instance.
+ *
+ * @return array
+ */
+ public function getMutatedAttributes()
+ {
+ $class = static::class;
+
+ if (! isset(static::$mutatorCache[$class])) {
+ static::cacheMutatedAttributes($class);
+ }
+
+ return static::$mutatorCache[$class];
+ }
+
+ /**
+ * Extract and cache all the mutated attributes of a class.
+ *
+ * @param string $class
+ *
+ * @return void
+ */
+ public static function cacheMutatedAttributes($class)
+ {
+ static::$mutatorCache[$class] = collect(static::getMutatorMethods($class))->reject(function ($match) {
+ return $match === 'First';
+ })->map(function ($match) {
+ return lcfirst($match);
+ })->all();
+ }
+
+ /**
+ * Get all of the attribute mutator methods.
+ *
+ * @param mixed $class
+ *
+ * @return array
+ */
+ protected static function getMutatorMethods($class)
+ {
+ preg_match_all('/(?<=^|;)get([^;]+?)Attribute(;|$)/', implode(';', get_class_methods($class)), $matches);
+
+ return $matches[1];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasEvents.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasEvents.php
new file mode 100644
index 0000000..1bc76d0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasEvents.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace LdapRecord\Models\Concerns;
+
+use Closure;
+use LdapRecord\Models\Events\Event;
+
+trait HasEvents
+{
+ /**
+ * Fires the specified model event.
+ *
+ * @param Event $event
+ *
+ * @return mixed
+ */
+ protected function fireModelEvent(Event $event)
+ {
+ return static::getConnectionContainer()->getEventDispatcher()->fire($event);
+ }
+
+ /**
+ * Listens to a model event.
+ *
+ * @param string $event
+ * @param Closure $listener
+ *
+ * @return mixed
+ */
+ protected function listenForModelEvent($event, Closure $listener)
+ {
+ return static::getConnectionContainer()->getEventDispatcher()->listen($event, $listener);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasGlobalScopes.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasGlobalScopes.php
new file mode 100644
index 0000000..c14abad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasGlobalScopes.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace LdapRecord\Models\Concerns;
+
+use Closure;
+use InvalidArgumentException;
+use LdapRecord\Models\Scope;
+
+trait HasGlobalScopes
+{
+ /**
+ * Register a new global scope on the model.
+ *
+ * @param Scope|Closure|string $scope
+ * @param Closure|null $implementation
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return mixed
+ */
+ public static function addGlobalScope($scope, Closure $implementation = null)
+ {
+ if (is_string($scope) && ! is_null($implementation)) {
+ return static::$globalScopes[static::class][$scope] = $implementation;
+ } elseif ($scope instanceof Closure) {
+ return static::$globalScopes[static::class][spl_object_hash($scope)] = $scope;
+ } elseif ($scope instanceof Scope) {
+ return static::$globalScopes[static::class][get_class($scope)] = $scope;
+ }
+
+ throw new InvalidArgumentException('Global scope must be an instance of Closure or Scope.');
+ }
+
+ /**
+ * Determine if a model has a global scope.
+ *
+ * @param Scope|string $scope
+ *
+ * @return bool
+ */
+ public static function hasGlobalScope($scope)
+ {
+ return ! is_null(static::getGlobalScope($scope));
+ }
+
+ /**
+ * Get a global scope registered with the model.
+ *
+ * @param Scope|string $scope
+ *
+ * @return Scope|Closure|null
+ */
+ public static function getGlobalScope($scope)
+ {
+ if (array_key_exists(static::class, static::$globalScopes)) {
+ $scopeName = is_string($scope) ? $scope : get_class($scope);
+
+ return array_key_exists($scopeName, static::$globalScopes[static::class])
+ ? static::$globalScopes[static::class][$scopeName]
+ : null;
+ }
+ }
+
+ /**
+ * Get the global scopes for this class instance.
+ *
+ * @return array
+ */
+ public function getGlobalScopes()
+ {
+ return array_key_exists(static::class, static::$globalScopes)
+ ? static::$globalScopes[static::class]
+ : [];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasPassword.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasPassword.php
new file mode 100644
index 0000000..9822456
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasPassword.php
@@ -0,0 +1,251 @@
+<?php
+
+namespace LdapRecord\Models\Concerns;
+
+use LdapRecord\ConnectionException;
+use LdapRecord\LdapRecordException;
+use LdapRecord\Models\Attributes\Password;
+
+trait HasPassword
+{
+ /**
+ * Set the password on the user.
+ *
+ * @param string|array $password
+ *
+ * @throws ConnectionException
+ */
+ public function setPasswordAttribute($password)
+ {
+ $this->validateSecureConnection();
+
+ // Here we will attempt to determine the password hash method in use
+ // by parsing the users hashed password (if it as available). If a
+ // method is determined, we will override the default here.
+ if (! ($method = $this->determinePasswordHashMethod())) {
+ $method = $this->getPasswordHashMethod();
+ }
+
+ // If the password given is an array, we can assume we
+ // are changing the password for the current user.
+ if (is_array($password)) {
+ $this->setChangedPassword(
+ $this->getHashedPassword($method, $password[0], $this->getPasswordSalt($method)),
+ $this->getHashedPassword($method, $password[1]),
+ $this->getPasswordAttributeName()
+ );
+ }
+ // Otherwise, we will assume the password is being
+ // reset, overwriting the one currently in place.
+ else {
+ $this->setPassword(
+ $this->getHashedPassword($method, $password),
+ $this->getPasswordAttributeName()
+ );
+ }
+ }
+
+ /**
+ * Alias for setting the password on the user.
+ *
+ * @param string|array $password
+ *
+ * @throws ConnectionException
+ */
+ public function setUnicodepwdAttribute($password)
+ {
+ $this->setPasswordAttribute($password);
+ }
+
+ /**
+ * An accessor for retrieving the user's hashed password value.
+ *
+ * @return string|null
+ */
+ public function getPasswordAttribute()
+ {
+ return $this->getAttribute($this->getPasswordAttributeName())[0] ?? null;
+ }
+
+ /**
+ * Get the name of the attribute that contains the user's password.
+ *
+ * @return string
+ */
+ public function getPasswordAttributeName()
+ {
+ if (property_exists($this, 'passwordAttribute')) {
+ return $this->passwordAttribute;
+ }
+
+ if (method_exists($this, 'passwordAttribute')) {
+ return $this->passwordAttribute();
+ }
+
+ return 'unicodepwd';
+ }
+
+ /**
+ * Get the name of the method to use for hashing the user's password.
+ *
+ * @return string
+ */
+ public function getPasswordHashMethod()
+ {
+ if (property_exists($this, 'passwordHashMethod')) {
+ return $this->passwordHashMethod;
+ }
+
+ if (method_exists($this, 'passwordHashMethod')) {
+ return $this->passwordHashMethod();
+ }
+
+ return 'encode';
+ }
+
+ /**
+ * Set the changed password.
+ *
+ * @param string $oldPassword
+ * @param string $newPassword
+ * @param string $attribute
+ *
+ * @return void
+ */
+ protected function setChangedPassword($oldPassword, $newPassword, $attribute)
+ {
+ // Create batch modification for removing the old password.
+ $this->addModification(
+ $this->newBatchModification(
+ $attribute,
+ LDAP_MODIFY_BATCH_REMOVE,
+ [$oldPassword]
+ )
+ );
+
+ // Create batch modification for adding the new password.
+ $this->addModification(
+ $this->newBatchModification(
+ $attribute,
+ LDAP_MODIFY_BATCH_ADD,
+ [$newPassword]
+ )
+ );
+ }
+
+ /**
+ * Set the password on the model.
+ *
+ * @param string $password
+ * @param string $attribute
+ *
+ * @return void
+ */
+ protected function setPassword($password, $attribute)
+ {
+ $this->addModification(
+ $this->newBatchModification(
+ $attribute,
+ LDAP_MODIFY_BATCH_REPLACE,
+ [$password]
+ )
+ );
+ }
+
+ /**
+ * Encode / hash the given password.
+ *
+ * @param string $method
+ * @param string $password
+ * @param string $salt
+ *
+ * @throws LdapRecordException
+ *
+ * @return string
+ */
+ protected function getHashedPassword($method, $password, $salt = null)
+ {
+ if (! method_exists(Password::class, $method)) {
+ throw new LdapRecordException("Password hashing method [{$method}] does not exist.");
+ }
+
+ if (Password::hashMethodRequiresSalt($method)) {
+ return Password::{$method}($password, $salt);
+ }
+
+ return Password::{$method}($password);
+ }
+
+ /**
+ * Validates that the current LDAP connection is secure.
+ *
+ * @throws ConnectionException
+ *
+ * @return void
+ */
+ protected function validateSecureConnection()
+ {
+ $connection = $this->getConnection();
+
+ if ($connection->isConnected()) {
+ $secure = $connection->getLdapConnection()->canChangePasswords();
+ } else {
+ $secure = $connection->getConfiguration()->get('use_ssl') || $connection->getConfiguration()->get('use_tls');
+ }
+
+ if (! $secure) {
+ throw new ConnectionException(
+ 'You must be connected to your LDAP server with TLS or SSL to perform this operation.'
+ );
+ }
+ }
+
+ /**
+ * Attempt to retrieve the password's salt.
+ *
+ * @param string $method
+ *
+ * @return string|null
+ */
+ public function getPasswordSalt($method)
+ {
+ if (! Password::hashMethodRequiresSalt($method)) {
+ return;
+ }
+
+ return Password::getSalt($this->password);
+ }
+
+ /**
+ * Determine the password hash method to use from the users current password.
+ *
+ * @return string|void
+ */
+ public function determinePasswordHashMethod()
+ {
+ if (! $password = $this->password) {
+ return;
+ }
+
+ if (! $method = Password::getHashMethod($password)) {
+ return;
+ }
+
+ [,$algo] = array_pad(
+ Password::getHashMethodAndAlgo($password) ?? [],
+ $length = 2,
+ $value = null
+ );
+
+ switch ($algo) {
+ case Password::CRYPT_SALT_TYPE_MD5:
+ return 'md5'.$method;
+ case Password::CRYPT_SALT_TYPE_SHA256:
+ return 'sha256'.$method;
+ case Password::CRYPT_SALT_TYPE_SHA512:
+ return 'sha512'.$method;
+ default:
+ return $method;
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasRelationships.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasRelationships.php
new file mode 100644
index 0000000..a8a5cac
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasRelationships.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace LdapRecord\Models\Concerns;
+
+use LdapRecord\Models\Relations\HasMany;
+use LdapRecord\Models\Relations\HasManyIn;
+use LdapRecord\Models\Relations\HasOne;
+use LdapRecord\Support\Arr;
+
+trait HasRelationships
+{
+ /**
+ * Returns a new has one relationship.
+ *
+ * @param mixed $related
+ * @param string $relationKey
+ * @param string $foreignKey
+ *
+ * @return HasOne
+ */
+ public function hasOne($related, $relationKey, $foreignKey = 'dn')
+ {
+ return new HasOne($this->newQuery(), $this, $related, $relationKey, $foreignKey);
+ }
+
+ /**
+ * Returns a new has many relationship.
+ *
+ * @param mixed $related
+ * @param string $relationKey
+ * @param string $foreignKey
+ *
+ * @return HasMany
+ */
+ public function hasMany($related, $relationKey, $foreignKey = 'dn')
+ {
+ return new HasMany($this->newQuery(), $this, $related, $relationKey, $foreignKey, $this->guessRelationshipName());
+ }
+
+ /**
+ * Returns a new has many in relationship.
+ *
+ * @param mixed $related
+ * @param string $relationKey
+ * @param string $foreignKey
+ *
+ * @return HasManyIn
+ */
+ public function hasManyIn($related, $relationKey, $foreignKey = 'dn')
+ {
+ return new HasManyIn($this->newQuery(), $this, $related, $relationKey, $foreignKey, $this->guessRelationshipName());
+ }
+
+ /**
+ * Get the relationships name.
+ *
+ * @return string|null
+ */
+ protected function guessRelationshipName()
+ {
+ return Arr::last(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3))['function'];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasScopes.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasScopes.php
new file mode 100644
index 0000000..6c97cf9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasScopes.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace LdapRecord\Models\Concerns;
+
+trait HasScopes
+{
+ /**
+ * Begin querying the direct descendants of the model.
+ *
+ * @return \LdapRecord\Query\Model\Builder
+ */
+ public function descendants()
+ {
+ return $this->in($this->getDn())->listing();
+ }
+
+ /**
+ * Begin querying the direct ancestors of the model.
+ *
+ * @return \LdapRecord\Query\Model\Builder
+ */
+ public function ancestors()
+ {
+ $parent = $this->getParentDn($this->getDn());
+
+ return $this->in($this->getParentDn($parent))->listing();
+ }
+
+ /**
+ * Begin querying the direct siblings of the model.
+ *
+ * @return \LdapRecord\Query\Model\Builder
+ */
+ public function siblings()
+ {
+ return $this->in($this->getParentDn($this->getDn()))->listing();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HidesAttributes.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HidesAttributes.php
new file mode 100644
index 0000000..9cc2100
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HidesAttributes.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace LdapRecord\Models\Concerns;
+
+/**
+ * @author Taylor Otwell
+ *
+ * @see https://laravel.com
+ */
+trait HidesAttributes
+{
+ /**
+ * The attributes that should be hidden for serialization.
+ *
+ * @var array
+ */
+ protected $hidden = [];
+
+ /**
+ * The attributes that should be visible in serialization.
+ *
+ * @var array
+ */
+ protected $visible = [];
+
+ /**
+ * Get the hidden attributes for the model.
+ *
+ * @return array
+ */
+ public function getHidden()
+ {
+ return array_map(function ($key) {
+ return $this->normalizeAttributeKey($key);
+ }, $this->hidden);
+ }
+
+ /**
+ * Set the hidden attributes for the model.
+ *
+ * @param array $hidden
+ *
+ * @return $this
+ */
+ public function setHidden(array $hidden)
+ {
+ $this->hidden = $hidden;
+
+ return $this;
+ }
+
+ /**
+ * Add hidden attributes for the model.
+ *
+ * @param array|string|null $attributes
+ *
+ * @return void
+ */
+ public function addHidden($attributes = null)
+ {
+ $this->hidden = array_merge(
+ $this->hidden,
+ is_array($attributes) ? $attributes : func_get_args()
+ );
+ }
+
+ /**
+ * Get the visible attributes for the model.
+ *
+ * @return array
+ */
+ public function getVisible()
+ {
+ return array_map(function ($key) {
+ return $this->normalizeAttributeKey($key);
+ }, $this->visible);
+ }
+
+ /**
+ * Set the visible attributes for the model.
+ *
+ * @param array $visible
+ *
+ * @return $this
+ */
+ public function setVisible(array $visible)
+ {
+ $this->visible = $visible;
+
+ return $this;
+ }
+
+ /**
+ * Add visible attributes for the model.
+ *
+ * @param array|string|null $attributes
+ *
+ * @return void
+ */
+ public function addVisible($attributes = null)
+ {
+ $this->visible = array_merge(
+ $this->visible,
+ is_array($attributes) ? $attributes : func_get_args()
+ );
+ }
+
+ /**
+ * Make the given, typically hidden, attributes visible.
+ *
+ * @param array|string $attributes
+ *
+ * @return $this
+ */
+ public function makeVisible($attributes)
+ {
+ $this->hidden = array_diff($this->hidden, (array) $attributes);
+
+ if (! empty($this->visible)) {
+ $this->addVisible($attributes);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Make the given, typically visible, attributes hidden.
+ *
+ * @param array|string $attributes
+ *
+ * @return $this
+ */
+ public function makeHidden($attributes)
+ {
+ $attributes = (array) $attributes;
+
+ $this->visible = array_diff($this->visible, $attributes);
+
+ $this->hidden = array_unique(array_merge($this->hidden, $attributes));
+
+ return $this;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DetectsResetIntegers.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DetectsResetIntegers.php
new file mode 100644
index 0000000..8712ef7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DetectsResetIntegers.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace LdapRecord\Models;
+
+trait DetectsResetIntegers
+{
+ /**
+ * Determine if the given value is an LDAP reset integer.
+ *
+ * The integer values '0' and '-1' can be used on certain
+ * LDAP attributes to instruct the server to reset the
+ * value to an 'unset' or 'cleared' state.
+ *
+ * @param mixed $value
+ *
+ * @return bool
+ */
+ protected function valueIsResetInteger($value)
+ {
+ return in_array($value, [0, -1], $strict = true);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DirectoryServer/Entry.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DirectoryServer/Entry.php
new file mode 100644
index 0000000..1bf8325
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DirectoryServer/Entry.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace LdapRecord\Models\DirectoryServer;
+
+use LdapRecord\Models\Model;
+
+class Entry extends Model
+{
+ /**
+ * The attribute key that contains the models object GUID.
+ *
+ * @var string
+ */
+ protected $guidKey = 'gidNumber';
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DirectoryServer/Group.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DirectoryServer/Group.php
new file mode 100644
index 0000000..49a6e0a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DirectoryServer/Group.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace LdapRecord\Models\DirectoryServer;
+
+class Group extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'groupOfUniqueNames',
+ 'posixGroup',
+ ];
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DirectoryServer/User.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DirectoryServer/User.php
new file mode 100644
index 0000000..430588b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/DirectoryServer/User.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace LdapRecord\Models\DirectoryServer;
+
+class User extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'nsPerson',
+ 'nsAccount',
+ 'nsOrgPerson',
+ 'posixAccount',
+ ];
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Entry.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Entry.php
new file mode 100644
index 0000000..dcfda57
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Entry.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models;
+
+class Entry extends Model
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Created.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Created.php
new file mode 100644
index 0000000..c101235
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Created.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+class Created extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Creating.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Creating.php
new file mode 100644
index 0000000..c4e6ad7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Creating.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+class Creating extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Deleted.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Deleted.php
new file mode 100644
index 0000000..7852659
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Deleted.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+class Deleted extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Deleting.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Deleting.php
new file mode 100644
index 0000000..9a0810d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Deleting.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+class Deleting extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Event.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Event.php
new file mode 100644
index 0000000..20de0b7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Event.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+use LdapRecord\Models\Model;
+
+abstract class Event
+{
+ /**
+ * The model that the event is being triggered on.
+ *
+ * @var Model
+ */
+ protected $model;
+
+ /**
+ * Constructor.
+ *
+ * @param Model $model
+ */
+ public function __construct(Model $model)
+ {
+ $this->model = $model;
+ }
+
+ /**
+ * Returns the model that generated the event.
+ *
+ * @return Model
+ */
+ public function getModel()
+ {
+ return $this->model;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Renamed.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Renamed.php
new file mode 100644
index 0000000..0f02b6d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Renamed.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+class Renamed extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Renaming.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Renaming.php
new file mode 100644
index 0000000..83427ca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Renaming.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+use LdapRecord\Models\Model;
+
+class Renaming extends Event
+{
+ /**
+ * The models RDN.
+ *
+ * @var string
+ */
+ protected $rdn;
+
+ /**
+ * The models new parent DN.
+ *
+ * @var string
+ */
+ protected $newParentDn;
+
+ /**
+ * Constructor.
+ *
+ * @param Model $model
+ * @param string $rdn
+ * @param string $newParentDn
+ */
+ public function __construct(Model $model, $rdn, $newParentDn)
+ {
+ parent::__construct($model);
+
+ $this->rdn = $rdn;
+ $this->newParentDn = $newParentDn;
+ }
+
+ /**
+ * Get the models RDN.
+ *
+ * @return string
+ */
+ public function getRdn()
+ {
+ return $this->rdn;
+ }
+
+ /**
+ * Get the models parent DN.
+ *
+ * @return string
+ */
+ public function getNewParentDn()
+ {
+ return $this->newParentDn;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Saved.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Saved.php
new file mode 100644
index 0000000..cf9c5ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Saved.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+class Saved extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Saving.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Saving.php
new file mode 100644
index 0000000..0c99403
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Saving.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+class Saving extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Updated.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Updated.php
new file mode 100644
index 0000000..b0dd611
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Updated.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+class Updated extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Updating.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Updating.php
new file mode 100644
index 0000000..20ae60c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Events/Updating.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Events;
+
+class Updating extends Event
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/Entry.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/Entry.php
new file mode 100644
index 0000000..7fdda9c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/Entry.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace LdapRecord\Models\FreeIPA;
+
+use LdapRecord\Connection;
+use LdapRecord\Models\Entry as BaseEntry;
+use LdapRecord\Models\FreeIPA\Scopes\AddEntryUuidToSelects;
+use LdapRecord\Models\Types\FreeIPA;
+use LdapRecord\Query\Model\FreeIpaBuilder;
+
+/** @mixin FreeIpaBuilder */
+class Entry extends BaseEntry implements FreeIPA
+{
+ /**
+ * The attribute key that contains the models object GUID.
+ *
+ * @var string
+ */
+ protected $guidKey = 'ipauniqueid';
+
+ /**
+ * The default attributes that should be mutated to dates.
+ *
+ * @var array
+ */
+ protected $defaultDates = [
+ 'krblastpwdchange' => 'ldap',
+ 'krbpasswordexpiration' => 'ldap',
+ ];
+
+ /**
+ * @inheritdoc
+ */
+ protected static function boot()
+ {
+ parent::boot();
+
+ // Here we'll add a global scope to all FreeIPA models to ensure the
+ // Entry UUID is always selected on each query. This attribute is
+ // virtual, so it must be manually selected to be included.
+ static::addGlobalScope(new AddEntryUuidToSelects());
+ }
+
+ /**
+ * Create a new query builder.
+ *
+ * @param Connection $connection
+ *
+ * @return FreeIpaBuilder
+ */
+ public function newQueryBuilder(Connection $connection)
+ {
+ return new FreeIpaBuilder($connection);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/Group.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/Group.php
new file mode 100644
index 0000000..10fd934
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/Group.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace LdapRecord\Models\FreeIPA;
+
+class Group extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'groupofnames',
+ 'nestedgroup',
+ 'ipausergroup',
+ 'posixgroup',
+ ];
+
+ /**
+ * The groups relationship.
+ *
+ * Retrieves groups that the current group is apart of.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function groups()
+ {
+ return $this->hasMany(self::class, 'member');
+ }
+
+ /**
+ * Retrieve the members of the group.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function members()
+ {
+ return $this->hasMany(User::class, 'memberof')->using($this, 'member');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/Scopes/AddEntryUuidToSelects.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/Scopes/AddEntryUuidToSelects.php
new file mode 100644
index 0000000..039c05e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/Scopes/AddEntryUuidToSelects.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace LdapRecord\Models\FreeIPA\Scopes;
+
+use LdapRecord\Models\Model;
+use LdapRecord\Models\Scope;
+use LdapRecord\Query\Model\Builder;
+
+class AddEntryUuidToSelects implements Scope
+{
+ /**
+ * Add the entry UUID to the selected attributes.
+ *
+ * @param Builder $query
+ * @param Model $model
+ *
+ * @return void
+ */
+ public function apply(Builder $query, Model $model)
+ {
+ empty($query->columns)
+ ? $query->addSelect(['*', $model->getGuidKey()])
+ : $query->addSelect($model->getGuidKey());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/User.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/User.php
new file mode 100644
index 0000000..24c7f3b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/FreeIPA/User.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace LdapRecord\Models\FreeIPA;
+
+class User extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'person',
+ 'inetorgperson',
+ 'organizationalperson',
+ ];
+
+ /**
+ * Retrieve groups that the current user is apart of.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function groups()
+ {
+ return $this->hasMany(Group::class, 'member');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Model.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Model.php
new file mode 100644
index 0000000..6ba24b4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Model.php
@@ -0,0 +1,1441 @@
+<?php
+
+namespace LdapRecord\Models;
+
+use ArrayAccess;
+use InvalidArgumentException;
+use JsonSerializable;
+use LdapRecord\Connection;
+use LdapRecord\Container;
+use LdapRecord\EscapesValues;
+use LdapRecord\Models\Attributes\DistinguishedName;
+use LdapRecord\Models\Attributes\Guid;
+use LdapRecord\Models\Events\Renamed;
+use LdapRecord\Models\Events\Renaming;
+use LdapRecord\Query\Model\Builder;
+use LdapRecord\Support\Arr;
+use UnexpectedValueException;
+
+/** @mixin Builder */
+abstract class Model implements ArrayAccess, JsonSerializable
+{
+ use EscapesValues;
+ use Concerns\HasEvents;
+ use Concerns\HasScopes;
+ use Concerns\HasAttributes;
+ use Concerns\HasGlobalScopes;
+ use Concerns\HidesAttributes;
+ use Concerns\HasRelationships;
+
+ /**
+ * Indicates if the model exists in the LDAP directory.
+ *
+ * @var bool
+ */
+ public $exists = false;
+
+ /**
+ * Indicates whether the model was created during the current request lifecycle.
+ *
+ * @var bool
+ */
+ public $wasRecentlyCreated = false;
+
+ /**
+ * Indicates whether the model was renamed during the current request lifecycle.
+ *
+ * @var bool
+ */
+ public $wasRecentlyRenamed = false;
+
+ /**
+ * The models distinguished name.
+ *
+ * @var string|null
+ */
+ protected $dn;
+
+ /**
+ * The base DN of where the model should be created in.
+ *
+ * @var string|null
+ */
+ protected $in;
+
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [];
+
+ /**
+ * The connection container instance.
+ *
+ * @var Container
+ */
+ protected static $container;
+
+ /**
+ * The LDAP connection name for the model.
+ *
+ * @var string|null
+ */
+ protected $connection;
+
+ /**
+ * The attribute key that contains the models object GUID.
+ *
+ * @var string
+ */
+ protected $guidKey = 'objectguid';
+
+ /**
+ * Contains the models modifications.
+ *
+ * @var array
+ */
+ protected $modifications = [];
+
+ /**
+ * The array of global scopes on the model.
+ *
+ * @var array
+ */
+ protected static $globalScopes = [];
+
+ /**
+ * The array of booted models.
+ *
+ * @var array
+ */
+ protected static $booted = [];
+
+ /**
+ * Constructor.
+ *
+ * @param array $attributes
+ */
+ public function __construct(array $attributes = [])
+ {
+ $this->bootIfNotBooted();
+
+ $this->fill($attributes);
+ }
+
+ /**
+ * Check if the model needs to be booted and if so, do it.
+ *
+ * @return void
+ */
+ protected function bootIfNotBooted()
+ {
+ if (! isset(static::$booted[static::class])) {
+ static::$booted[static::class] = true;
+
+ static::boot();
+ }
+ }
+
+ /**
+ * The "booting" method of the model.
+ *
+ * @return void
+ */
+ protected static function boot()
+ {
+ //
+ }
+
+ /**
+ * Clear the list of booted models so they will be re-booted.
+ *
+ * @return void
+ */
+ public static function clearBootedModels()
+ {
+ static::$booted = [];
+
+ static::$globalScopes = [];
+ }
+
+ /**
+ * Handle dynamic method calls into the model.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ if (method_exists($this, $method)) {
+ return $this->$method(...$parameters);
+ }
+
+ return $this->newQuery()->$method(...$parameters);
+ }
+
+ /**
+ * Handle dynamic static method calls into the method.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public static function __callStatic($method, $parameters)
+ {
+ return (new static())->$method(...$parameters);
+ }
+
+ /**
+ * Returns the models distinguished name.
+ *
+ * @return string|null
+ */
+ public function getDn()
+ {
+ return $this->dn;
+ }
+
+ /**
+ * Set the models distinguished name.
+ *
+ * @param string $dn
+ *
+ * @return static
+ */
+ public function setDn($dn)
+ {
+ $this->dn = (string) $dn;
+
+ return $this;
+ }
+
+ /**
+ * Get the LDAP connection for the model.
+ *
+ * @return Connection
+ */
+ public function getConnection()
+ {
+ return static::resolveConnection($this->getConnectionName());
+ }
+
+ /**
+ * Get the current connection name for the model.
+ *
+ * @return string
+ */
+ public function getConnectionName()
+ {
+ return $this->connection;
+ }
+
+ /**
+ * Set the connection associated with the model.
+ *
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function setConnection($name)
+ {
+ $this->connection = $name;
+
+ return $this;
+ }
+
+ /**
+ * Begin querying the model on a given connection.
+ *
+ * @param string|null $connection
+ *
+ * @return Builder
+ */
+ public static function on($connection = null)
+ {
+ $instance = new static();
+
+ $instance->setConnection($connection);
+
+ return $instance->newQuery();
+ }
+
+ /**
+ * Get all the models from the directory.
+ *
+ * @param array|mixed $attributes
+ *
+ * @return Collection|static[]
+ */
+ public static function all($attributes = ['*'])
+ {
+ return static::query()->select($attributes)->paginate();
+ }
+
+ /**
+ * Begin querying the model.
+ *
+ * @return Builder
+ */
+ public static function query()
+ {
+ return (new static())->newQuery();
+ }
+
+ /**
+ * Get a new query for builder filtered by the current models object classes.
+ *
+ * @return Builder
+ */
+ public function newQuery()
+ {
+ return $this->registerModelScopes(
+ $this->newQueryWithoutScopes()
+ );
+ }
+
+ /**
+ * Get a new query builder that doesn't have any global scopes.
+ *
+ * @return Builder
+ */
+ public function newQueryWithoutScopes()
+ {
+ return static::resolveConnection(
+ $this->getConnectionName()
+ )->query()->model($this);
+ }
+
+ /**
+ * Create a new query builder.
+ *
+ * @param Connection $connection
+ *
+ * @return Builder
+ */
+ public function newQueryBuilder(Connection $connection)
+ {
+ return new Builder($connection);
+ }
+
+ /**
+ * Create a new model instance.
+ *
+ * @param array $attributes
+ *
+ * @return static
+ */
+ public function newInstance(array $attributes = [])
+ {
+ return (new static($attributes))->setConnection($this->getConnectionName());
+ }
+
+ /**
+ * Resolve a connection instance.
+ *
+ * @param string|null $connection
+ *
+ * @return Connection
+ */
+ public static function resolveConnection($connection = null)
+ {
+ return static::getConnectionContainer()->get($connection);
+ }
+
+ /**
+ * Get the connection container.
+ *
+ * @return Container
+ */
+ public static function getConnectionContainer()
+ {
+ return static::$container ?? static::getDefaultConnectionContainer();
+ }
+
+ /**
+ * Get the default singleton container instance.
+ *
+ * @return Container
+ */
+ public static function getDefaultConnectionContainer()
+ {
+ return Container::getInstance();
+ }
+
+ /**
+ * Set the connection container.
+ *
+ * @param Container $container
+ *
+ * @return void
+ */
+ public static function setConnectionContainer(Container $container)
+ {
+ static::$container = $container;
+ }
+
+ /**
+ * Unset the connection container.
+ *
+ * @return void
+ */
+ public static function unsetConnectionContainer()
+ {
+ static::$container = null;
+ }
+
+ /**
+ * Register the query scopes for this builder instance.
+ *
+ * @param Builder $builder
+ *
+ * @return Builder
+ */
+ public function registerModelScopes($builder)
+ {
+ $this->applyObjectClassScopes($builder);
+
+ $this->registerGlobalScopes($builder);
+
+ return $builder;
+ }
+
+ /**
+ * Register the global model scopes.
+ *
+ * @param Builder $builder
+ *
+ * @return Builder
+ */
+ public function registerGlobalScopes($builder)
+ {
+ foreach ($this->getGlobalScopes() as $identifier => $scope) {
+ $builder->withGlobalScope($identifier, $scope);
+ }
+
+ return $builder;
+ }
+
+ /**
+ * Apply the model object class scopes to the given builder instance.
+ *
+ * @param Builder $query
+ *
+ * @return void
+ */
+ public function applyObjectClassScopes(Builder $query)
+ {
+ foreach (static::$objectClasses as $objectClass) {
+ $query->where('objectclass', '=', $objectClass);
+ }
+ }
+
+ /**
+ * Returns the models distinguished name when the model is converted to a string.
+ *
+ * @return null|string
+ */
+ public function __toString()
+ {
+ return $this->getDn();
+ }
+
+ /**
+ * Returns a new batch modification.
+ *
+ * @param string|null $attribute
+ * @param string|int|null $type
+ * @param array $values
+ *
+ * @return BatchModification
+ */
+ public function newBatchModification($attribute = null, $type = null, $values = [])
+ {
+ return new BatchModification($attribute, $type, $values);
+ }
+
+ /**
+ * Returns a new collection with the specified items.
+ *
+ * @param mixed $items
+ *
+ * @return Collection
+ */
+ public function newCollection($items = [])
+ {
+ return new Collection($items);
+ }
+
+ /**
+ * Dynamically retrieve attributes on the object.
+ *
+ * @param mixed $key
+ *
+ * @return bool
+ */
+ public function __get($key)
+ {
+ return $this->getAttribute($key);
+ }
+
+ /**
+ * Dynamically set attributes on the object.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function __set($key, $value)
+ {
+ return $this->setAttribute($key, $value);
+ }
+
+ /**
+ * Determine if the given offset exists.
+ *
+ * @param string $offset
+ *
+ * @return bool
+ */
+ public function offsetExists($offset)
+ {
+ return ! is_null($this->getAttribute($offset));
+ }
+
+ /**
+ * Get the value for a given offset.
+ *
+ * @param string $offset
+ *
+ * @return mixed
+ */
+ public function offsetGet($offset)
+ {
+ return $this->getAttribute($offset);
+ }
+
+ /**
+ * Set the value at the given offset.
+ *
+ * @param string $offset
+ * @param mixed $value
+ *
+ * @return void
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->setAttribute($offset, $value);
+ }
+
+ /**
+ * Unset the value at the given offset.
+ *
+ * @param string $offset
+ *
+ * @return void
+ */
+ public function offsetUnset($offset)
+ {
+ unset($this->attributes[$offset]);
+ }
+
+ /**
+ * Determine if an attribute exists on the model.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function __isset($key)
+ {
+ return $this->offsetExists($key);
+ }
+
+ /**
+ * Unset an attribute on the model.
+ *
+ * @param string $key
+ *
+ * @return void
+ */
+ public function __unset($key)
+ {
+ $this->offsetUnset($key);
+ }
+
+ /**
+ * Convert the object into something JSON serializable.
+ *
+ * @return array
+ */
+ public function jsonSerialize()
+ {
+ return $this->attributesToArray();
+ }
+
+ /**
+ * Converts extra attributes for JSON serialization.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+ protected function convertAttributesForJson(array $attributes = [])
+ {
+ // If the model has a GUID set, we need to convert
+ // it due to it being in binary. Otherwise we'll
+ // receive a JSON serialization exception.
+ if ($this->hasAttribute($this->guidKey)) {
+ return array_replace($attributes, [
+ $this->guidKey => [$this->getConvertedGuid()],
+ ]);
+ }
+
+ return $attributes;
+ }
+
+ /**
+ * Reload a fresh model instance from the directory.
+ *
+ * @return static|false
+ */
+ public function fresh()
+ {
+ if (! $this->exists) {
+ return false;
+ }
+
+ return $this->newQuery()->find($this->dn);
+ }
+
+ /**
+ * Determine if two models have the same distinguished name and belong to the same connection.
+ *
+ * @param static $model
+ *
+ * @return bool
+ */
+ public function is(self $model)
+ {
+ return $this->dn == $model->getDn() && $this->getConnectionName() == $model->getConnectionName();
+ }
+
+ /**
+ * Hydrate a new collection of models from LDAP search results.
+ *
+ * @param array $records
+ *
+ * @return Collection
+ */
+ public function hydrate($records)
+ {
+ return $this->newCollection($records)->transform(function ($attributes) {
+ return $attributes instanceof static
+ ? $attributes
+ : static::newInstance()->setRawAttributes($attributes);
+ });
+ }
+
+ /**
+ * Converts the current model into the given model.
+ *
+ * @param Model $into
+ *
+ * @return Model
+ */
+ public function convert(self $into)
+ {
+ $into->setDn($this->getDn());
+ $into->setConnection($this->getConnectionName());
+
+ $this->exists
+ ? $into->setRawAttributes($this->getAttributes())
+ : $into->fill($this->getAttributes());
+
+ return $into;
+ }
+
+ /**
+ * Refreshes the current models attributes with the directory values.
+ *
+ * @return bool
+ */
+ public function refresh()
+ {
+ if ($model = $this->fresh()) {
+ $this->setRawAttributes($model->getAttributes());
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the model's batch modifications to be processed.
+ *
+ * @return array
+ */
+ public function getModifications()
+ {
+ $builtModifications = [];
+
+ foreach ($this->buildModificationsFromDirty() as $modification) {
+ $builtModifications[] = $modification->get();
+ }
+
+ return array_merge($this->modifications, $builtModifications);
+ }
+
+ /**
+ * Set the models batch modifications.
+ *
+ * @param array $modifications
+ *
+ * @return $this
+ */
+ public function setModifications(array $modifications = [])
+ {
+ $this->modifications = [];
+
+ foreach ($modifications as $modification) {
+ $this->addModification($modification);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds a batch modification to the model.
+ *
+ * @param array|BatchModification $mod
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function addModification($mod = [])
+ {
+ if ($mod instanceof BatchModification) {
+ $mod = $mod->get();
+ }
+
+ if ($this->isValidModification($mod)) {
+ $this->modifications[] = $mod;
+
+ return $this;
+ }
+
+ throw new InvalidArgumentException(
+ "The batch modification array does not include the mandatory 'attrib' or 'modtype' keys."
+ );
+ }
+
+ /**
+ * Get the model's guid attribute key name.
+ *
+ * @return string
+ */
+ public function getGuidKey()
+ {
+ return $this->guidKey;
+ }
+
+ /**
+ * Get the model's ANR attributes for querying when incompatible with ANR.
+ *
+ * @return array
+ */
+ public function getAnrAttributes()
+ {
+ return ['cn', 'sn', 'uid', 'name', 'mail', 'givenname', 'displayname'];
+ }
+
+ /**
+ * Get the name of the model, or the given DN.
+ *
+ * @param string|null $dn
+ *
+ * @return string|null
+ */
+ public function getName($dn = null)
+ {
+ return $this->newDn($dn ?? $this->dn)->name();
+ }
+
+ /**
+ * Get the head attribute of the model, or the given DN.
+ *
+ * @param string|null $dn
+ *
+ * @return string|null
+ */
+ public function getHead($dn = null)
+ {
+ return $this->newDn($dn ?? $this->dn)->head();
+ }
+
+ /**
+ * Get the RDN of the model, of the given DN.
+ *
+ * @param string|null
+ *
+ * @return string|null
+ */
+ public function getRdn($dn = null)
+ {
+ return $this->newDn($dn ?? $this->dn)->relative();
+ }
+
+ /**
+ * Get the parent distinguished name of the model, or the given DN.
+ *
+ * @param string|null
+ *
+ * @return string|null
+ */
+ public function getParentDn($dn = null)
+ {
+ return $this->newDn($dn ?? $this->dn)->parent();
+ }
+
+ /**
+ * Create a new Distinguished Name object.
+ *
+ * @param string|null $dn
+ *
+ * @return DistinguishedName
+ */
+ public function newDn($dn = null)
+ {
+ return new DistinguishedName($dn);
+ }
+
+ /**
+ * Get the model's object GUID key.
+ *
+ * @return void
+ */
+ public function getObjectGuidKey()
+ {
+ return $this->guidKey;
+ }
+
+ /**
+ * Get the model's binary object GUID.
+ *
+ * @see https://msdn.microsoft.com/en-us/library/ms679021(v=vs.85).aspx
+ *
+ * @return string|null
+ */
+ public function getObjectGuid()
+ {
+ return $this->getFirstAttribute($this->guidKey);
+ }
+
+ /**
+ * Get the model's object classes.
+ *
+ * @return array
+ */
+ public function getObjectClasses()
+ {
+ return $this->getAttribute('objectclass') ?: [];
+ }
+
+ /**
+ * Get the model's string GUID.
+ *
+ * @return string|null
+ */
+ public function getConvertedGuid()
+ {
+ try {
+ return (string) new Guid($this->getObjectGuid());
+ } catch (InvalidArgumentException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Determine if the current model is a direct descendant of the given.
+ *
+ * @param static|string $parent
+ *
+ * @return bool
+ */
+ public function isChildOf($parent)
+ {
+ return $this->newDn($this->getDn())->isChildOf(
+ $this->newDn((string) $parent)
+ );
+ }
+
+ /**
+ * Determine if the current model is a direct ascendant of the given.
+ *
+ * @param static|string $child
+ *
+ * @return bool
+ */
+ public function isParentOf($child)
+ {
+ return $this->newDn($this->getDn())->isParentOf(
+ $this->newDn((string) $child)
+ );
+ }
+
+ /**
+ * Determine if the current model is a descendant of the given.
+ *
+ * @param static|string $model
+ *
+ * @return bool
+ */
+ public function isDescendantOf($model)
+ {
+ return $this->dnIsInside($this->getDn(), $model);
+ }
+
+ /**
+ * Determine if the current model is a ancestor of the given.
+ *
+ * @param static|string $model
+ *
+ * @return bool
+ */
+ public function isAncestorOf($model)
+ {
+ return $this->dnIsInside($model, $this->getDn());
+ }
+
+ /**
+ * Determines if the DN is inside of the parent DN.
+ *
+ * @param static|string $dn
+ * @param static|string $parentDn
+ *
+ * @return bool
+ */
+ protected function dnIsInside($dn, $parentDn)
+ {
+ return $this->newDn((string) $dn)->isDescendantOf(
+ $this->newDn($parentDn)
+ );
+ }
+
+ /**
+ * Set the base DN of where the model should be created in.
+ *
+ * @param static|string $dn
+ *
+ * @return $this
+ */
+ public function inside($dn)
+ {
+ $this->in = $dn instanceof self ? $dn->getDn() : $dn;
+
+ return $this;
+ }
+
+ /**
+ * Save the model to the directory.
+ *
+ * @param array $attributes The attributes to update or create for the current entry.
+ *
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ public function save(array $attributes = [])
+ {
+ $this->fill($attributes);
+
+ $this->fireModelEvent(new Events\Saving($this));
+
+ $this->exists ? $this->performUpdate() : $this->performInsert();
+
+ $this->fireModelEvent(new Events\Saved($this));
+
+ $this->in = null;
+ }
+
+ /**
+ * Inserts the model into the directory.
+ *
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ protected function performInsert()
+ {
+ // Here we will populate the models object classes if it
+ // does not already have any set. An LDAP object cannot
+ // be successfully created in the server without them.
+ if (! $this->hasAttribute('objectclass')) {
+ $this->setAttribute('objectclass', static::$objectClasses);
+ }
+
+ $query = $this->newQuery();
+
+ // If the model does not currently have a distinguished
+ // name, we will attempt to generate one automatically
+ // using the current query builder's DN as the base.
+ if (empty($this->getDn())) {
+ $this->setDn($this->getCreatableDn());
+ }
+
+ $this->fireModelEvent(new Events\Creating($this));
+
+ // Here we perform the insert of new object in the directory,
+ // but filter out any empty attributes before sending them
+ // to the server. LDAP servers will throw an exception if
+ // attributes have been given empty or null values.
+ $query->insert($this->getDn(), array_filter($this->getAttributes()));
+
+ $this->fireModelEvent(new Events\Created($this));
+
+ $this->syncOriginal();
+
+ $this->exists = true;
+
+ $this->wasRecentlyCreated = true;
+ }
+
+ /**
+ * Updates the model in the directory.
+ *
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ protected function performUpdate()
+ {
+ if (! count($modifications = $this->getModifications())) {
+ return;
+ }
+
+ $this->fireModelEvent(new Events\Updating($this));
+
+ $this->newQuery()->update($this->dn, $modifications);
+
+ $this->fireModelEvent(new Events\Updated($this));
+
+ $this->syncOriginal();
+
+ $this->modifications = [];
+ }
+
+ /**
+ * Create the model in the directory.
+ *
+ * @param array $attributes The attributes for the new entry.
+ *
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return Model
+ */
+ public static function create(array $attributes = [])
+ {
+ $instance = new static($attributes);
+
+ $instance->save();
+
+ return $instance;
+ }
+
+ /**
+ * Create an attribute on the model.
+ *
+ * @param string $attribute The attribute to create
+ * @param mixed $value The value of the new attribute
+ *
+ * @throws ModelDoesNotExistException
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ public function createAttribute($attribute, $value)
+ {
+ $this->validateExistence();
+
+ $this->newQuery()->insertAttributes($this->dn, [$attribute => (array) $value]);
+
+ $this->addAttributeValue($attribute, $value);
+ }
+
+ /**
+ * Update the model.
+ *
+ * @param array $attributes The attributes to update for the current entry.
+ *
+ * @throws ModelDoesNotExistException
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ public function update(array $attributes = [])
+ {
+ $this->validateExistence();
+
+ $this->save($attributes);
+ }
+
+ /**
+ * Update the model attribute with the specified value.
+ *
+ * @param string $attribute The attribute to modify
+ * @param mixed $value The new value for the attribute
+ *
+ * @throws ModelDoesNotExistException
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ public function updateAttribute($attribute, $value)
+ {
+ $this->validateExistence();
+
+ $this->newQuery()->updateAttributes($this->dn, [$attribute => (array) $value]);
+
+ $this->addAttributeValue($attribute, $value);
+ }
+
+ /**
+ * Destroy the models for the given distinguished names.
+ *
+ * @param Collection|array|string $dns
+ * @param bool $recursive
+ *
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return int
+ */
+ public static function destroy($dns, $recursive = false)
+ {
+ $count = 0;
+
+ $dns = is_string($dns) ? (array) $dns : $dns;
+
+ $instance = new static();
+
+ foreach ($dns as $dn) {
+ if (! $model = $instance->find($dn)) {
+ continue;
+ }
+
+ $model->delete($recursive);
+
+ $count++;
+ }
+
+ return $count;
+ }
+
+ /**
+ * Delete the model from the directory.
+ *
+ * Throws a ModelNotFoundException if the current model does
+ * not exist or does not contain a distinguished name.
+ *
+ * @param bool $recursive Whether to recursively delete leaf nodes (models that are children).
+ *
+ * @throws ModelDoesNotExistException
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ public function delete($recursive = false)
+ {
+ $this->validateExistence();
+
+ $this->fireModelEvent(new Events\Deleting($this));
+
+ if ($recursive) {
+ $this->deleteLeafNodes();
+ }
+
+ $this->newQuery()->delete($this->dn);
+
+ // If the deletion is successful, we will mark the model
+ // as non-existing, and then fire the deleted event so
+ // developers can hook in and run further operations.
+ $this->exists = false;
+
+ $this->fireModelEvent(new Events\Deleted($this));
+ }
+
+ /**
+ * Deletes leaf nodes that are attached to the model.
+ *
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return Collection
+ */
+ protected function deleteLeafNodes()
+ {
+ return $this->newQueryWithoutScopes()
+ ->in($this->dn)
+ ->listing()
+ ->paginate()
+ ->each(function (self $model) {
+ $model->delete($recursive = true);
+ });
+ }
+
+ /**
+ * Delete an attribute on the model.
+ *
+ * @param string|array $attributes The attribute(s) to delete
+ *
+ * Delete specific values in attributes:
+ *
+ * ["memberuid" => "jdoe"]
+ *
+ * Delete an entire attribute:
+ *
+ * ["memberuid" => []]
+ *
+ * @throws ModelDoesNotExistException
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ public function deleteAttribute($attributes)
+ {
+ $this->validateExistence();
+
+ $attributes = $this->makeDeletableAttributes($attributes);
+
+ $this->newQuery()->deleteAttributes($this->dn, $attributes);
+
+ foreach ($attributes as $attribute => $value) {
+ // If the attribute value is empty, we can assume the
+ // attribute was completely deleted from the model.
+ // We will pull the attribute out and continue on.
+ if (empty($value)) {
+ unset($this->attributes[$attribute]);
+ }
+ // Otherwise, only specific attribute values have been
+ // removed. We will determine which ones have been
+ // removed and update the attributes value.
+ elseif (Arr::exists($this->attributes, $attribute)) {
+ $this->attributes[$attribute] = array_values(
+ array_diff($this->attributes[$attribute], (array) $value)
+ );
+ }
+ }
+
+ $this->syncOriginal();
+ }
+
+ /**
+ * Make a deletable attribute array.
+ *
+ * @param string|array $attributes
+ *
+ * @return array
+ */
+ protected function makeDeletableAttributes($attributes)
+ {
+ $delete = [];
+
+ foreach (Arr::wrap($attributes) as $key => $value) {
+ is_int($key)
+ ? $delete[$value] = []
+ : $delete[$key] = Arr::wrap($value);
+ }
+
+ return $delete;
+ }
+
+ /**
+ * Move the model into the given new parent.
+ *
+ * For example: $user->move($ou);
+ *
+ * @param static|string $newParentDn The new parent of the current model.
+ * @param bool $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
+ *
+ * @throws UnexpectedValueException
+ * @throws ModelDoesNotExistException
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ public function move($newParentDn, $deleteOldRdn = true)
+ {
+ $this->validateExistence();
+
+ if (! $rdn = $this->getRdn()) {
+ throw new UnexpectedValueException('Current model does not contain an RDN to move.');
+ }
+
+ $this->rename($rdn, $newParentDn, $deleteOldRdn);
+ }
+
+ /**
+ * Rename the model to a new RDN and new parent.
+ *
+ * @param string $rdn The models new relative distinguished name. Example: "cn=JohnDoe"
+ * @param static|string|null $newParentDn The models new parent distinguished name (if moving). Leave this null if you are only renaming. Example: "ou=MovedUsers,dc=acme,dc=org"
+ * @param bool|true $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
+ *
+ * @throws ModelDoesNotExistException
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ public function rename($rdn, $newParentDn = null, $deleteOldRdn = true)
+ {
+ $this->validateExistence();
+
+ if ($newParentDn instanceof self) {
+ $newParentDn = $newParentDn->getDn();
+ }
+
+ if (is_null($newParentDn)) {
+ $newParentDn = $this->getParentDn($this->dn);
+ }
+
+ // If the RDN and the new parent DN are the same as the current,
+ // we will simply return here to prevent a rename operation
+ // being sent, which would fail anyway in such case.
+ if (
+ $rdn === $this->getRdn()
+ && $newParentDn === $this->getParentDn()
+ ) {
+ return;
+ }
+
+ $this->fireModelEvent(new Renaming($this, $rdn, $newParentDn));
+
+ $this->newQuery()->rename($this->dn, $rdn, $newParentDn, $deleteOldRdn);
+
+ // If the model was successfully renamed, we will set
+ // its new DN so any further updates to the model
+ // can be performed without any issues.
+ $this->dn = implode(',', [$rdn, $newParentDn]);
+
+ $map = $this->newDn($this->dn)->assoc();
+
+ // Here we'll populate the models new primary
+ // RDN attribute on the model so we do not
+ // have to re-synchronize with the server.
+ $modelNameAttribute = key($map);
+
+ $this->attributes[$modelNameAttribute]
+ = $this->original[$modelNameAttribute]
+ = [reset($map[$modelNameAttribute])];
+
+ $this->fireModelEvent(new Renamed($this));
+
+ $this->wasRecentlyRenamed = true;
+ }
+
+ /**
+ * Get a distinguished name that is creatable for the model.
+ *
+ * @param string|null $name
+ * @param string|null $attribute
+ *
+ * @return string
+ */
+ public function getCreatableDn($name = null, $attribute = null)
+ {
+ return implode(',', [
+ $this->getCreatableRdn($name, $attribute),
+ $this->in ?? $this->newQuery()->getbaseDn(),
+ ]);
+ }
+
+ /**
+ * Get a creatable (escaped) RDN for the model.
+ *
+ * @param string|null $name
+ * @param string|null $attribute
+ *
+ * @return string
+ */
+ public function getCreatableRdn($name = null, $attribute = null)
+ {
+ $attribute = $attribute ?? $this->getCreatableRdnAttribute();
+
+ $name = $this->escape(
+ $name ?? $this->getFirstAttribute($attribute)
+ )->dn();
+
+ return "$attribute=$name";
+ }
+
+ /**
+ * Get the creatable RDN attribute name.
+ *
+ * @return string
+ */
+ protected function getCreatableRdnAttribute()
+ {
+ return 'cn';
+ }
+
+ /**
+ * Determines if the given modification is valid.
+ *
+ * @param mixed $mod
+ *
+ * @return bool
+ */
+ protected function isValidModification($mod)
+ {
+ return Arr::accessible($mod)
+ && Arr::exists($mod, BatchModification::KEY_MODTYPE)
+ && Arr::exists($mod, BatchModification::KEY_ATTRIB);
+ }
+
+ /**
+ * Builds the models modifications from its dirty attributes.
+ *
+ * @return BatchModification[]
+ */
+ protected function buildModificationsFromDirty()
+ {
+ $modifications = [];
+
+ foreach ($this->getDirty() as $attribute => $values) {
+ $modification = $this->newBatchModification($attribute, null, (array) $values);
+
+ if (Arr::exists($this->original, $attribute)) {
+ // If the attribute we're modifying has an original value, we will
+ // give the BatchModification object its values to automatically
+ // determine which type of LDAP operation we need to perform.
+ $modification->setOriginal($this->original[$attribute]);
+ }
+
+ if (! $modification->build()->isValid()) {
+ continue;
+ }
+
+ $modifications[] = $modification;
+ }
+
+ return $modifications;
+ }
+
+ /**
+ * Validates that the current model exists.
+ *
+ * @throws ModelDoesNotExistException
+ *
+ * @return void
+ */
+ protected function validateExistence()
+ {
+ if (! $this->exists || is_null($this->dn)) {
+ throw ModelDoesNotExistException::forModel($this);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ModelDoesNotExistException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ModelDoesNotExistException.php
new file mode 100644
index 0000000..2dd2ba9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ModelDoesNotExistException.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace LdapRecord\Models;
+
+use LdapRecord\LdapRecordException;
+
+class ModelDoesNotExistException extends LdapRecordException
+{
+ /**
+ * The class name of the model that does not exist.
+ *
+ * @var Model
+ */
+ protected $model;
+
+ /**
+ * Create a new exception for the given model.
+ *
+ * @param Model $model
+ *
+ * @return ModelDoesNotExistException
+ */
+ public static function forModel(Model $model)
+ {
+ return (new static())->setModel($model);
+ }
+
+ /**
+ * Set the model that does not exist.
+ *
+ * @param Model $model
+ *
+ * @return ModelDoesNotExistException
+ */
+ public function setModel(Model $model)
+ {
+ $this->model = $model;
+
+ $class = get_class($model);
+
+ $this->message = "Model [{$class}] does not exist.";
+
+ return $this;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ModelNotFoundException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ModelNotFoundException.php
new file mode 100644
index 0000000..be88bab
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/ModelNotFoundException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace LdapRecord\Models;
+
+use LdapRecord\Query\ObjectNotFoundException;
+
+class ModelNotFoundException extends ObjectNotFoundException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/Entry.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/Entry.php
new file mode 100644
index 0000000..b7ad37a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/Entry.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace LdapRecord\Models\OpenLDAP;
+
+use LdapRecord\Connection;
+use LdapRecord\Models\Entry as BaseEntry;
+use LdapRecord\Models\OpenLDAP\Scopes\AddEntryUuidToSelects;
+use LdapRecord\Models\Types\OpenLDAP;
+use LdapRecord\Query\Model\OpenLdapBuilder;
+
+/** @mixin OpenLdapBuilder */
+class Entry extends BaseEntry implements OpenLDAP
+{
+ /**
+ * The attribute key that contains the models object GUID.
+ *
+ * @var string
+ */
+ protected $guidKey = 'entryuuid';
+
+ /**
+ * @inheritdoc
+ */
+ protected static function boot()
+ {
+ parent::boot();
+
+ // Here we'll add a global scope to all OpenLDAP models to ensure the
+ // Entry UUID is always selected on each query. This attribute is
+ // virtual, so it must be manually selected to be included.
+ static::addGlobalScope(new AddEntryUuidToSelects());
+ }
+
+ /**
+ * Create a new query builder.
+ *
+ * @param Connection $connection
+ *
+ * @return OpenLdapBuilder
+ */
+ public function newQueryBuilder(Connection $connection)
+ {
+ return new OpenLdapBuilder($connection);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/Group.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/Group.php
new file mode 100644
index 0000000..2d8d94e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/Group.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace LdapRecord\Models\OpenLDAP;
+
+class Group extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'groupofuniquenames',
+ ];
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/OrganizationalUnit.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/OrganizationalUnit.php
new file mode 100644
index 0000000..7ae0a37
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/OrganizationalUnit.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace LdapRecord\Models\OpenLDAP;
+
+class OrganizationalUnit extends Entry
+{
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'organizationalunit',
+ ];
+
+ /**
+ * Get the creatable RDN attribute name.
+ *
+ * @return string
+ */
+ public function getCreatableRdnAttribute()
+ {
+ return 'ou';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/Scopes/AddEntryUuidToSelects.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/Scopes/AddEntryUuidToSelects.php
new file mode 100644
index 0000000..54376c2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/Scopes/AddEntryUuidToSelects.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace LdapRecord\Models\OpenLDAP\Scopes;
+
+use LdapRecord\Models\Model;
+use LdapRecord\Models\Scope;
+use LdapRecord\Query\Model\Builder;
+
+class AddEntryUuidToSelects implements Scope
+{
+ /**
+ * Add the entry UUID to the selected attributes.
+ *
+ * @param Builder $query
+ * @param Model $model
+ *
+ * @return void
+ */
+ public function apply(Builder $query, Model $model)
+ {
+ empty($query->columns)
+ ? $query->addSelect(['*', $model->getGuidKey()])
+ : $query->addSelect($model->getGuidKey());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/User.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/User.php
new file mode 100644
index 0000000..b37f390
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/OpenLDAP/User.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace LdapRecord\Models\OpenLDAP;
+
+use Illuminate\Contracts\Auth\Authenticatable;
+use LdapRecord\Models\Concerns\CanAuthenticate;
+use LdapRecord\Models\Concerns\HasPassword;
+
+class User extends Entry implements Authenticatable
+{
+ use HasPassword;
+ use CanAuthenticate;
+
+ /**
+ * The password's attribute name.
+ *
+ * @var string
+ */
+ protected $passwordAttribute = 'userpassword';
+
+ /**
+ * The password's hash method.
+ *
+ * @var string
+ */
+ protected $passwordHashMethod = 'ssha';
+
+ /**
+ * The object classes of the LDAP model.
+ *
+ * @var array
+ */
+ public static $objectClasses = [
+ 'top',
+ 'person',
+ 'organizationalperson',
+ 'inetorgperson',
+ ];
+
+ /**
+ * The groups relationship.
+ *
+ * Retrieves groups that the user is apart of.
+ *
+ * @return \LdapRecord\Models\Relations\HasMany
+ */
+ public function groups()
+ {
+ return $this->hasMany(Group::class, 'memberuid', 'uid');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasMany.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasMany.php
new file mode 100644
index 0000000..d8dfa08
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasMany.php
@@ -0,0 +1,344 @@
+<?php
+
+namespace LdapRecord\Models\Relations;
+
+use Closure;
+use LdapRecord\DetectsErrors;
+use LdapRecord\LdapRecordException;
+use LdapRecord\Models\Model;
+use LdapRecord\Models\ModelNotFoundException;
+use LdapRecord\Query\Collection;
+
+class HasMany extends OneToMany
+{
+ use DetectsErrors;
+
+ /**
+ * The model to use for attaching / detaching.
+ *
+ * @var Model
+ */
+ protected $using;
+
+ /**
+ * The attribute key to use for attaching / detaching.
+ *
+ * @var string
+ */
+ protected $usingKey;
+
+ /**
+ * The pagination page size.
+ *
+ * @var int
+ */
+ protected $pageSize = 1000;
+
+ /**
+ * The exceptions to bypass for each relation operation.
+ *
+ * @var array
+ */
+ protected $bypass = [
+ 'attach' => [
+ 'Already exists', 'Type or value exists',
+ ],
+ 'detach' => [
+ 'No such attribute', 'Server is unwilling to perform',
+ ],
+ ];
+
+ /**
+ * Set the model and attribute to use for attaching / detaching.
+ *
+ * @param Model $using
+ * @param string $usingKey
+ *
+ * @return $this
+ */
+ public function using(Model $using, $usingKey)
+ {
+ $this->using = $using;
+ $this->usingKey = $usingKey;
+
+ return $this;
+ }
+
+ /**
+ * Set the pagination page size of the relation query.
+ *
+ * @param int $pageSize
+ *
+ * @return $this
+ */
+ public function setPageSize($pageSize)
+ {
+ $this->pageSize = $pageSize;
+
+ return $this;
+ }
+
+ /**
+ * Paginate the relation using the given page size.
+ *
+ * @param int $pageSize
+ *
+ * @return Collection
+ */
+ public function paginate($pageSize = 1000)
+ {
+ return $this->paginateOnceUsing($pageSize);
+ }
+
+ /**
+ * Paginate the relation using the page size once.
+ *
+ * @param int $pageSize
+ *
+ * @return Collection
+ */
+ protected function paginateOnceUsing($pageSize)
+ {
+ $size = $this->pageSize;
+
+ $result = $this->setPageSize($pageSize)->get();
+
+ $this->pageSize = $size;
+
+ return $result;
+ }
+
+ /**
+ * Chunk the relation results using the given callback.
+ *
+ * @param int $pageSize
+ * @param Closure $callback
+ *
+ * @return void
+ */
+ public function chunk($pageSize, Closure $callback)
+ {
+ $this->getRelationQuery()->chunk($pageSize, function ($entries) use ($callback) {
+ $callback($this->transformResults($entries));
+ });
+ }
+
+ /**
+ * Get the relationships results.
+ *
+ * @return Collection
+ */
+ public function getRelationResults()
+ {
+ return $this->transformResults(
+ $this->getRelationQuery()->paginate($this->pageSize)
+ );
+ }
+
+ /**
+ * Get the prepared relationship query.
+ *
+ * @return \LdapRecord\Query\Model\Builder
+ */
+ public function getRelationQuery()
+ {
+ $columns = $this->query->getSelects();
+
+ // We need to select the proper key to be able to retrieve its
+ // value from LDAP results. If we don't, we won't be able
+ // to properly attach / detach models from relation
+ // query results as the attribute will not exist.
+ $key = $this->using ? $this->usingKey : $this->relationKey;
+
+ // If the * character is missing from the attributes to select,
+ // we will add the key to the attributes to select and also
+ // validate that the key isn't already being selected
+ // to prevent stacking on multiple relation calls.
+ if (! in_array('*', $columns) && ! in_array($key, $columns)) {
+ $this->query->addSelect($key);
+ }
+
+ return $this->query->whereRaw(
+ $this->relationKey,
+ '=',
+ $this->getEscapedForeignValueFromModel($this->parent)
+ );
+ }
+
+ /**
+ * Attach a model to the relation.
+ *
+ * @param Model|string $model
+ *
+ * @return Model|string|false
+ */
+ public function attach($model)
+ {
+ return $this->attemptFailableOperation(
+ $this->buildAttachCallback($model),
+ $this->bypass['attach'],
+ $model
+ );
+ }
+
+ /**
+ * Build the attach callback.
+ *
+ * @param Model|string $model
+ *
+ * @return \Closure
+ */
+ protected function buildAttachCallback($model)
+ {
+ return function () use ($model) {
+ $foreign = $this->getAttachableForeignValue($model);
+
+ if ($this->using) {
+ return $this->using->createAttribute($this->usingKey, $foreign);
+ }
+
+ if (! $model instanceof Model) {
+ $model = $this->getForeignModelByValueOrFail($model);
+ }
+
+ return $model->createAttribute($this->relationKey, $foreign);
+ };
+ }
+
+ /**
+ * Attach a collection of models to the parent instance.
+ *
+ * @param iterable $models
+ *
+ * @return iterable
+ */
+ public function attachMany($models)
+ {
+ foreach ($models as $model) {
+ $this->attach($model);
+ }
+
+ return $models;
+ }
+
+ /**
+ * Detach the model from the relation.
+ *
+ * @param Model|string $model
+ *
+ * @return Model|string|false
+ */
+ public function detach($model)
+ {
+ return $this->attemptFailableOperation(
+ $this->buildDetachCallback($model),
+ $this->bypass['detach'],
+ $model
+ );
+ }
+
+ /**
+ * Build the detach callback.
+ *
+ * @param Model|string $model
+ *
+ * @return \Closure
+ */
+ protected function buildDetachCallback($model)
+ {
+ return function () use ($model) {
+ $foreign = $this->getAttachableForeignValue($model);
+
+ if ($this->using) {
+ return $this->using->deleteAttribute([$this->usingKey => $foreign]);
+ }
+
+ if (! $model instanceof Model) {
+ $model = $this->getForeignModelByValueOrFail($model);
+ }
+
+ return $model->deleteAttribute([$this->relationKey => $foreign]);
+ };
+ }
+
+ /**
+ * Get the attachable foreign value from the model.
+ *
+ * @param Model|string $model
+ *
+ * @return string
+ */
+ protected function getAttachableForeignValue($model)
+ {
+ if ($model instanceof Model) {
+ return $this->using
+ ? $this->getForeignValueFromModel($model)
+ : $this->getParentForeignValue();
+ }
+
+ return $this->using ? $model : $this->getParentForeignValue();
+ }
+
+ /**
+ * Get the foreign model by the given value, or fail.
+ *
+ * @param string $model
+ *
+ * @throws ModelNotFoundException
+ *
+ * @return Model
+ */
+ protected function getForeignModelByValueOrFail($model)
+ {
+ if (! is_null($model = $this->getForeignModelByValue($model))) {
+ return $model;
+ }
+
+ throw ModelNotFoundException::forQuery(
+ $this->query->getUnescapedQuery(),
+ $this->query->getDn()
+ );
+ }
+
+ /**
+ * Attempt a failable operation and return the value if successful.
+ *
+ * If a bypassable exception is encountered, the value will be returned.
+ *
+ * @param callable $operation
+ * @param string|array $bypass
+ * @param mixed $value
+ *
+ * @throws LdapRecordException
+ *
+ * @return mixed
+ */
+ protected function attemptFailableOperation($operation, $bypass, $value)
+ {
+ try {
+ $operation();
+
+ return $value;
+ } catch (LdapRecordException $e) {
+ if ($this->errorContainsMessage($e->getMessage(), $bypass)) {
+ return $value;
+ }
+
+ throw $e;
+ }
+ }
+
+ /**
+ * Detach all relation models.
+ *
+ * @return Collection
+ */
+ public function detachAll()
+ {
+ return $this->onceWithoutMerging(function () {
+ return $this->get()->each(function (Model $model) {
+ $this->detach($model);
+ });
+ });
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasManyIn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasManyIn.php
new file mode 100644
index 0000000..303a144
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasManyIn.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace LdapRecord\Models\Relations;
+
+use LdapRecord\Query\Collection;
+
+class HasManyIn extends OneToMany
+{
+ /**
+ * Get the relationships results.
+ *
+ * @return Collection
+ */
+ public function getRelationResults()
+ {
+ $results = $this->parent->newCollection();
+
+ foreach ((array) $this->parent->getAttribute($this->relationKey) as $value) {
+ if ($foreign = $this->getForeignModelByValue($value)) {
+ $results->push($foreign);
+ }
+ }
+
+ return $this->transformResults($results);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasOne.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasOne.php
new file mode 100644
index 0000000..9a9b2f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasOne.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace LdapRecord\Models\Relations;
+
+use LdapRecord\Models\Model;
+
+class HasOne extends Relation
+{
+ /**
+ * Get the results of the relationship.
+ *
+ * @return \LdapRecord\Query\Collection
+ */
+ public function getResults()
+ {
+ $model = $this->getForeignModelByValue(
+ $this->getFirstAttributeValue($this->parent, $this->relationKey)
+ );
+
+ return $this->transformResults(
+ $this->parent->newCollection($model ? [$model] : null)
+ );
+ }
+
+ /**
+ * Attach a model instance to the parent model.
+ *
+ * @param Model|string $model
+ *
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return Model|string
+ */
+ public function attach($model)
+ {
+ $foreign = $model instanceof Model
+ ? $this->getForeignValueFromModel($model)
+ : $model;
+
+ $this->parent->setAttribute($this->relationKey, $foreign)->save();
+
+ return $model;
+ }
+
+ /**
+ * Detach the related model from the parent.
+ *
+ * @throws \LdapRecord\LdapRecordException
+ *
+ * @return void
+ */
+ public function detach()
+ {
+ $this->parent->setAttribute($this->relationKey, null)->save();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/OneToMany.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/OneToMany.php
new file mode 100644
index 0000000..d0a407c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/OneToMany.php
@@ -0,0 +1,186 @@
+<?php
+
+namespace LdapRecord\Models\Relations;
+
+use LdapRecord\Models\Model;
+use LdapRecord\Query\Collection;
+use LdapRecord\Query\Model\Builder;
+
+abstract class OneToMany extends Relation
+{
+ /**
+ * The relation to merge results with.
+ *
+ * @var OneToMany|null
+ */
+ protected $with;
+
+ /**
+ * The name of the relationship.
+ *
+ * @var string
+ */
+ protected $relationName;
+
+ /**
+ * Whether to include recursive results.
+ *
+ * @var bool
+ */
+ protected $recursive = false;
+
+ /**
+ * Constructor.
+ *
+ * @param Builder $query
+ * @param Model $parent
+ * @param string $related
+ * @param string $relationKey
+ * @param string $foreignKey
+ * @param string $relationName
+ */
+ public function __construct(Builder $query, Model $parent, $related, $relationKey, $foreignKey, $relationName)
+ {
+ $this->relationName = $relationName;
+
+ parent::__construct($query, $parent, $related, $relationKey, $foreignKey);
+ }
+
+ /**
+ * Set the relation to load with its parent.
+ *
+ * @param OneToMany $relation
+ *
+ * @return $this
+ */
+ public function with(Relation $relation)
+ {
+ $this->with = $relation;
+
+ return $this;
+ }
+
+ /**
+ * Whether to include recursive results.
+ *
+ * @param bool $enable
+ *
+ * @return $this
+ */
+ public function recursive($enable = true)
+ {
+ $this->recursive = $enable;
+
+ return $this;
+ }
+
+ /**
+ * Get the immediate relationships results.
+ *
+ * @return Collection
+ */
+ abstract public function getRelationResults();
+
+ /**
+ * Get the results of the relationship.
+ *
+ * @return Collection
+ */
+ public function getResults()
+ {
+ $results = $this->recursive
+ ? $this->getRecursiveResults()
+ : $this->getRelationResults();
+
+ return $results->merge(
+ $this->getMergingRelationResults()
+ );
+ }
+
+ /**
+ * Execute the callback excluding the merged query result.
+ *
+ * @param callable $callback
+ *
+ * @return mixed
+ */
+ protected function onceWithoutMerging($callback)
+ {
+ $merging = $this->with;
+
+ $this->with = null;
+
+ $result = $callback();
+
+ $this->with = $merging;
+
+ return $result;
+ }
+
+ /**
+ * Get the relation name.
+ *
+ * @return string
+ */
+ public function getRelationName()
+ {
+ return $this->relationName;
+ }
+
+ /**
+ * Get the results of the merging 'with' relation.
+ *
+ * @return Collection
+ */
+ protected function getMergingRelationResults()
+ {
+ return $this->with
+ ? $this->with->recursive($this->recursive)->get()
+ : $this->parent->newCollection();
+ }
+
+ /**
+ * Get the results for the models relation recursively.
+ *
+ * @param string[] $loaded The distinguished names of models already loaded
+ *
+ * @return Collection
+ */
+ protected function getRecursiveResults(array $loaded = [])
+ {
+ $results = $this->getRelationResults()->reject(function (Model $model) use ($loaded) {
+ // Here we will exclude the models that we have already
+ // loaded the recursive results for so we don't run
+ // into issues with circular relations in LDAP.
+ return in_array($model->getDn(), $loaded);
+ });
+
+ foreach ($results as $model) {
+ $loaded[] = $model->getDn();
+
+ // Finally, we will fetch the related models relations,
+ // passing along our loaded models, to ensure we do
+ // not attempt fetching already loaded relations.
+ $results = $results->merge(
+ $this->getRecursiveRelationResults($model, $loaded)
+ );
+ }
+
+ return $results;
+ }
+
+ /**
+ * Get the recursive relation results for given model.
+ *
+ * @param Model $model
+ * @param array $loaded
+ *
+ * @return Collection
+ */
+ protected function getRecursiveRelationResults(Model $model, array $loaded)
+ {
+ return method_exists($model, $this->relationName)
+ ? $model->{$this->relationName}()->getRecursiveResults($loaded)
+ : $model->newCollection();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/Relation.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/Relation.php
new file mode 100644
index 0000000..1b108fd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/Relation.php
@@ -0,0 +1,368 @@
+<?php
+
+namespace LdapRecord\Models\Relations;
+
+use LdapRecord\Models\Entry;
+use LdapRecord\Models\Model;
+use LdapRecord\Query\Collection;
+use LdapRecord\Query\Model\Builder;
+
+/**
+ * @method bool exists($models = null) Determine if the relation contains all of the given models, or any models
+ * @method bool contains($models) Determine if any of the given models are contained in the relation
+ */
+abstract class Relation
+{
+ /**
+ * The underlying LDAP query.
+ *
+ * @var Builder
+ */
+ protected $query;
+
+ /**
+ * The parent model instance.
+ *
+ * @var Model
+ */
+ protected $parent;
+
+ /**
+ * The related models.
+ *
+ * @var array
+ */
+ protected $related;
+
+ /**
+ * The relation key.
+ *
+ * @var string
+ */
+ protected $relationKey;
+
+ /**
+ * The foreign key.
+ *
+ * @var string
+ */
+ protected $foreignKey;
+
+ /**
+ * The default relation model.
+ *
+ * @var string
+ */
+ protected $default = Entry::class;
+
+ /**
+ * Constructor.
+ *
+ * @param Builder $query
+ * @param Model $parent
+ * @param mixed $related
+ * @param string $relationKey
+ * @param string $foreignKey
+ */
+ public function __construct(Builder $query, Model $parent, $related, $relationKey, $foreignKey)
+ {
+ $this->query = $query;
+ $this->parent = $parent;
+ $this->related = (array) $related;
+ $this->relationKey = $relationKey;
+ $this->foreignKey = $foreignKey;
+
+ $this->initRelation();
+ }
+
+ /**
+ * Handle dynamic method calls to the relationship.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ if (in_array($method, ['exists', 'contains'])) {
+ return $this->get('objectclass')->$method(...$parameters);
+ }
+
+ $result = $this->query->$method(...$parameters);
+
+ if ($result === $this->query) {
+ return $this;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get the results of the relationship.
+ *
+ * @return Collection
+ */
+ abstract public function getResults();
+
+ /**
+ * Execute the relationship query.
+ *
+ * @param array|string $columns
+ *
+ * @return Collection
+ */
+ public function get($columns = ['*'])
+ {
+ return $this->getResultsWithColumns($columns);
+ }
+
+ /**
+ * Get the results of the relationship while selecting the given columns.
+ *
+ * If the query columns are empty, the given columns are applied.
+ *
+ * @param array $columns
+ *
+ * @return Collection
+ */
+ protected function getResultsWithColumns($columns)
+ {
+ if (is_null($this->query->columns)) {
+ $this->query->select($columns);
+ }
+
+ return $this->getResults();
+ }
+
+ /**
+ * Get the first result of the relationship.
+ *
+ * @param array|string $columns
+ *
+ * @return Model|null
+ */
+ public function first($columns = ['*'])
+ {
+ return $this->get($columns)->first();
+ }
+
+ /**
+ * Prepare the relation query.
+ *
+ * @return static
+ */
+ public function initRelation()
+ {
+ $this->query
+ ->clearFilters()
+ ->withoutGlobalScopes()
+ ->setModel($this->getNewDefaultModel());
+
+ return $this;
+ }
+
+ /**
+ * Get the underlying query for the relation.
+ *
+ * @return Builder
+ */
+ public function getQuery()
+ {
+ return $this->query;
+ }
+
+ /**
+ * Get the parent model of the relation.
+ *
+ * @return Model
+ */
+ public function getParent()
+ {
+ return $this->parent;
+ }
+
+ /**
+ * Get the relation attribute key.
+ *
+ * @return string
+ */
+ public function getRelationKey()
+ {
+ return $this->relationKey;
+ }
+
+ /**
+ * Get the related model classes for the relation.
+ *
+ * @return array
+ */
+ public function getRelated()
+ {
+ return $this->related;
+ }
+
+ /**
+ * Get the relation foreign attribute key.
+ *
+ * @return string
+ */
+ public function getForeignKey()
+ {
+ return $this->foreignKey;
+ }
+
+ /**
+ * Get the class name of the default model.
+ *
+ * @return string
+ */
+ public function getDefaultModel()
+ {
+ return $this->default;
+ }
+
+ /**
+ * Get a new instance of the default model on the relation.
+ *
+ * @return Model
+ */
+ public function getNewDefaultModel()
+ {
+ $model = new $this->default();
+
+ $model->setConnection($this->parent->getConnectionName());
+
+ return $model;
+ }
+
+ /**
+ * Get the foreign model by the given value.
+ *
+ * @param string $value
+ *
+ * @return Model|null
+ */
+ protected function getForeignModelByValue($value)
+ {
+ return $this->foreignKeyIsDistinguishedName()
+ ? $this->query->find($value)
+ : $this->query->findBy($this->foreignKey, $value);
+ }
+
+ /**
+ * Returns the escaped foreign key value for use in an LDAP filter from the model.
+ *
+ * @param Model $model
+ *
+ * @return string
+ */
+ protected function getEscapedForeignValueFromModel(Model $model)
+ {
+ return $this->query->escape(
+ $this->getForeignValueFromModel($model)
+ )->both();
+ }
+
+ /**
+ * Get the relation parents foreign value.
+ *
+ * @return string
+ */
+ protected function getParentForeignValue()
+ {
+ return $this->getForeignValueFromModel($this->parent);
+ }
+
+ /**
+ * Get the foreign key value from the model.
+ *
+ * @param Model $model
+ *
+ * @return string
+ */
+ protected function getForeignValueFromModel(Model $model)
+ {
+ return $this->foreignKeyIsDistinguishedName()
+ ? $model->getDn()
+ : $this->getFirstAttributeValue($model, $this->foreignKey);
+ }
+
+ /**
+ * Get the first attribute value from the model.
+ *
+ * @param Model $model
+ * @param string $attribute
+ *
+ * @return string|null
+ */
+ protected function getFirstAttributeValue(Model $model, $attribute)
+ {
+ return $model->getFirstAttribute($attribute);
+ }
+
+ /**
+ * Transforms the results by converting the models into their related.
+ *
+ * @param Collection $results
+ *
+ * @return Collection
+ */
+ protected function transformResults(Collection $results)
+ {
+ $related = [];
+
+ foreach ($this->related as $relation) {
+ $related[$relation] = $relation::$objectClasses;
+ }
+
+ return $results->transform(function (Model $entry) use ($related) {
+ $model = $this->determineModelFromRelated($entry, $related);
+
+ return class_exists($model) ? $entry->convert(new $model()) : $entry;
+ });
+ }
+
+ /**
+ * Determines if the foreign key is a distinguished name.
+ *
+ * @return bool
+ */
+ protected function foreignKeyIsDistinguishedName()
+ {
+ return in_array($this->foreignKey, ['dn', 'distinguishedname']);
+ }
+
+ /**
+ * Determines the model from the given relations.
+ *
+ * @param Model $model
+ * @param array $related
+ *
+ * @return string|bool
+ */
+ protected function determineModelFromRelated(Model $model, array $related)
+ {
+ // We must normalize all the related models object class
+ // names to the same case so we are able to properly
+ // determine the owning model from search results.
+ return array_search(
+ $this->normalizeObjectClasses($model->getObjectClasses()),
+ array_map([$this, 'normalizeObjectClasses'], $related)
+ );
+ }
+
+ /**
+ * Sort and normalize the object classes.
+ *
+ * @param array $classes
+ *
+ * @return array
+ */
+ protected function normalizeObjectClasses($classes)
+ {
+ sort($classes);
+
+ return array_map('strtolower', $classes);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Scope.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Scope.php
new file mode 100644
index 0000000..321cae3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Scope.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace LdapRecord\Models;
+
+use LdapRecord\Query\Model\Builder;
+
+interface Scope
+{
+ /**
+ * Apply the scope to the given query.
+ *
+ * @param Builder $query
+ * @param Model $model
+ *
+ * @return void
+ */
+ public function apply(Builder $query, Model $model);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/ActiveDirectory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/ActiveDirectory.php
new file mode 100644
index 0000000..61d21ef
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/ActiveDirectory.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace LdapRecord\Models\Types;
+
+interface ActiveDirectory extends TypeInterface
+{
+ /**
+ * Returns the models object SID key.
+ *
+ * @return string
+ */
+ public function getObjectSidKey();
+
+ /**
+ * Returns the model's hex object SID.
+ *
+ * @see https://msdn.microsoft.com/en-us/library/ms679024(v=vs.85).aspx
+ *
+ * @return string
+ */
+ public function getObjectSid();
+
+ /**
+ * Returns the model's SID.
+ *
+ * @return string|null
+ */
+ public function getConvertedSid();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/FreeIPA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/FreeIPA.php
new file mode 100644
index 0000000..6831318
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/FreeIPA.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Types;
+
+interface FreeIPA extends TypeInterface
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/OpenLDAP.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/OpenLDAP.php
new file mode 100644
index 0000000..e63076e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/OpenLDAP.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Types;
+
+interface OpenLDAP extends TypeInterface
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/TypeInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/TypeInterface.php
new file mode 100644
index 0000000..8a45f32
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/TypeInterface.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Models\Types;
+
+interface TypeInterface
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/ArrayCacheStore.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/ArrayCacheStore.php
new file mode 100644
index 0000000..d7480a7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/ArrayCacheStore.php
@@ -0,0 +1,142 @@
+<?php
+
+namespace LdapRecord\Query;
+
+use Psr\SimpleCache\CacheInterface;
+
+class ArrayCacheStore implements CacheInterface
+{
+ use InteractsWithTime;
+
+ /**
+ * An array of stored values.
+ *
+ * @var array
+ */
+ protected $storage = [];
+
+ /**
+ * @inheritdoc
+ */
+ public function get($key, $default = null)
+ {
+ if (! isset($this->storage[$key])) {
+ return $default;
+ }
+
+ $item = $this->storage[$key];
+
+ $expiresAt = $item['expiresAt'] ?? 0;
+
+ if ($expiresAt !== 0 && $this->currentTime() > $expiresAt) {
+ $this->delete($key);
+
+ return $default;
+ }
+
+ return $item['value'];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function set($key, $value, $ttl = null)
+ {
+ $this->storage[$key] = [
+ 'value' => $value,
+ 'expiresAt' => $this->calculateExpiration($ttl),
+ ];
+
+ return true;
+ }
+
+ /**
+ * Get the expiration time of the key.
+ *
+ * @param int $seconds
+ *
+ * @return int
+ */
+ protected function calculateExpiration($seconds)
+ {
+ return $this->toTimestamp($seconds);
+ }
+
+ /**
+ * Get the UNIX timestamp for the given number of seconds.
+ *
+ * @param int $seconds
+ *
+ * @return int
+ */
+ protected function toTimestamp($seconds)
+ {
+ return $seconds > 0 ? $this->availableAt($seconds) : 0;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function delete($key)
+ {
+ unset($this->storage[$key]);
+
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function clear()
+ {
+ $this->storage = [];
+
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getMultiple($keys, $default = null)
+ {
+ $values = [];
+
+ foreach ($keys as $key) {
+ $values[$key] = $this->get($key, $default);
+ }
+
+ return $values;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setMultiple($values, $ttl = null)
+ {
+ foreach ($values as $key => $value) {
+ $this->set($key, $value, $ttl);
+ }
+
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function deleteMultiple($keys)
+ {
+ foreach ($keys as $key) {
+ $this->delete($key);
+ }
+
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function has($key)
+ {
+ return isset($this->storage[$key]);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Builder.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Builder.php
new file mode 100644
index 0000000..c75afa2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Builder.php
@@ -0,0 +1,1903 @@
+<?php
+
+namespace LdapRecord\Query;
+
+use BadMethodCallException;
+use Closure;
+use DateTimeInterface;
+use InvalidArgumentException;
+use LdapRecord\Connection;
+use LdapRecord\Container;
+use LdapRecord\EscapesValues;
+use LdapRecord\LdapInterface;
+use LdapRecord\LdapRecordException;
+use LdapRecord\Models\Model;
+use LdapRecord\Query\Events\QueryExecuted;
+use LdapRecord\Query\Model\Builder as ModelBuilder;
+use LdapRecord\Query\Pagination\LazyPaginator;
+use LdapRecord\Query\Pagination\Paginator;
+use LdapRecord\Support\Arr;
+use LdapRecord\Utilities;
+
+class Builder
+{
+ use EscapesValues;
+
+ /**
+ * The selected columns to retrieve on the query.
+ *
+ * @var array
+ */
+ public $columns;
+
+ /**
+ * The query filters.
+ *
+ * @var array
+ */
+ public $filters = [
+ 'and' => [],
+ 'or' => [],
+ 'raw' => [],
+ ];
+
+ /**
+ * The LDAP server controls to be sent.
+ *
+ * @var array
+ */
+ public $controls = [];
+
+ /**
+ * The size limit of the query.
+ *
+ * @var int
+ */
+ public $limit = 0;
+
+ /**
+ * Determines whether the current query is paginated.
+ *
+ * @var bool
+ */
+ public $paginated = false;
+
+ /**
+ * The distinguished name to perform searches upon.
+ *
+ * @var string|null
+ */
+ protected $dn;
+
+ /**
+ * The base distinguished name to perform searches inside.
+ *
+ * @var string|null
+ */
+ protected $baseDn;
+
+ /**
+ * The default query type.
+ *
+ * @var string
+ */
+ protected $type = 'search';
+
+ /**
+ * Determines whether the query is nested.
+ *
+ * @var bool
+ */
+ protected $nested = false;
+
+ /**
+ * Determines whether the query should be cached.
+ *
+ * @var bool
+ */
+ protected $caching = false;
+
+ /**
+ * How long the query should be cached until.
+ *
+ * @var DateTimeInterface|null
+ */
+ protected $cacheUntil = null;
+
+ /**
+ * Determines whether the query cache must be flushed.
+ *
+ * @var bool
+ */
+ protected $flushCache = false;
+
+ /**
+ * The current connection instance.
+ *
+ * @var Connection
+ */
+ protected $connection;
+
+ /**
+ * The current grammar instance.
+ *
+ * @var Grammar
+ */
+ protected $grammar;
+
+ /**
+ * The current cache instance.
+ *
+ * @var Cache|null
+ */
+ protected $cache;
+
+ /**
+ * Constructor.
+ *
+ * @param Connection $connection
+ */
+ public function __construct(Connection $connection)
+ {
+ $this->connection = $connection;
+ $this->grammar = new Grammar();
+ }
+
+ /**
+ * Set the current connection.
+ *
+ * @param Connection $connection
+ *
+ * @return $this
+ */
+ public function setConnection(Connection $connection)
+ {
+ $this->connection = $connection;
+
+ return $this;
+ }
+
+ /**
+ * Set the current filter grammar.
+ *
+ * @param Grammar $grammar
+ *
+ * @return $this
+ */
+ public function setGrammar(Grammar $grammar)
+ {
+ $this->grammar = $grammar;
+
+ return $this;
+ }
+
+ /**
+ * Set the cache to store query results.
+ *
+ * @param Cache|null $cache
+ *
+ * @return $this
+ */
+ public function setCache(Cache $cache = null)
+ {
+ $this->cache = $cache;
+
+ return $this;
+ }
+
+ /**
+ * Returns a new Query Builder instance.
+ *
+ * @param string $baseDn
+ *
+ * @return $this
+ */
+ public function newInstance($baseDn = null)
+ {
+ // We'll set the base DN of the new Builder so
+ // developers don't need to do this manually.
+ $dn = is_null($baseDn) ? $this->getDn() : $baseDn;
+
+ return (new static($this->connection))->setDn($dn);
+ }
+
+ /**
+ * Returns a new nested Query Builder instance.
+ *
+ * @param Closure|null $closure
+ *
+ * @return $this
+ */
+ public function newNestedInstance(Closure $closure = null)
+ {
+ $query = $this->newInstance()->nested();
+
+ if ($closure) {
+ $closure($query);
+ }
+
+ return $query;
+ }
+
+ /**
+ * Executes the LDAP query.
+ *
+ * @param string|array $columns
+ *
+ * @return Collection|array
+ */
+ public function get($columns = ['*'])
+ {
+ return $this->onceWithColumns(Arr::wrap($columns), function () {
+ return $this->query($this->getQuery());
+ });
+ }
+
+ /**
+ * Execute the given callback while selecting the given columns.
+ *
+ * After running the callback, the columns are reset to the original value.
+ *
+ * @param array $columns
+ * @param callable $callback
+ *
+ * @return mixed
+ */
+ protected function onceWithColumns($columns, $callback)
+ {
+ $original = $this->columns;
+
+ if (is_null($original)) {
+ $this->columns = $columns;
+ }
+
+ $result = $callback();
+
+ $this->columns = $original;
+
+ return $result;
+ }
+
+ /**
+ * Compiles and returns the current query string.
+ *
+ * @return string
+ */
+ public function getQuery()
+ {
+ // We need to ensure we have at least one filter, as
+ // no query results will be returned otherwise.
+ if (count(array_filter($this->filters)) === 0) {
+ $this->whereHas('objectclass');
+ }
+
+ return $this->grammar->compile($this);
+ }
+
+ /**
+ * Returns the unescaped query.
+ *
+ * @return string
+ */
+ public function getUnescapedQuery()
+ {
+ return Utilities::unescape($this->getQuery());
+ }
+
+ /**
+ * Returns the current Grammar instance.
+ *
+ * @return Grammar
+ */
+ public function getGrammar()
+ {
+ return $this->grammar;
+ }
+
+ /**
+ * Returns the current Cache instance.
+ *
+ * @return Cache|null
+ */
+ public function getCache()
+ {
+ return $this->cache;
+ }
+
+ /**
+ * Returns the current Connection instance.
+ *
+ * @return Connection
+ */
+ public function getConnection()
+ {
+ return $this->connection;
+ }
+
+ /**
+ * Returns the query type.
+ *
+ * @return string
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Set the base distinguished name of the query.
+ *
+ * @param Model|string $dn
+ *
+ * @return $this
+ */
+ public function setBaseDn($dn)
+ {
+ $this->baseDn = $this->substituteBaseInDn($dn);
+
+ return $this;
+ }
+
+ /**
+ * Get the base distinguished name of the query.
+ *
+ * @return string|null
+ */
+ public function getBaseDn()
+ {
+ return $this->baseDn;
+ }
+
+ /**
+ * Get the distinguished name of the query.
+ *
+ * @return string
+ */
+ public function getDn()
+ {
+ return $this->dn;
+ }
+
+ /**
+ * Set the distinguished name for the query.
+ *
+ * @param string|Model|null $dn
+ *
+ * @return $this
+ */
+ public function setDn($dn = null)
+ {
+ $this->dn = $this->substituteBaseInDn($dn);
+
+ return $this;
+ }
+
+ /**
+ * Substitute the base DN string template for the current base.
+ *
+ * @param Model|string $dn
+ *
+ * @return string
+ */
+ protected function substituteBaseInDn($dn)
+ {
+ return str_replace(
+ '{base}',
+ $this->baseDn,
+ $dn instanceof Model ? $dn->getDn() : $dn
+ );
+ }
+
+ /**
+ * Alias for setting the distinguished name for the query.
+ *
+ * @param string|Model|null $dn
+ *
+ * @return $this
+ */
+ public function in($dn = null)
+ {
+ return $this->setDn($dn);
+ }
+
+ /**
+ * Set the size limit of the current query.
+ *
+ * @param int $limit
+ *
+ * @return $this
+ */
+ public function limit($limit = 0)
+ {
+ $this->limit = $limit;
+
+ return $this;
+ }
+
+ /**
+ * Returns a new query for the given model.
+ *
+ * @param Model $model
+ *
+ * @return ModelBuilder
+ */
+ public function model(Model $model)
+ {
+ return $model->newQueryBuilder($this->connection)
+ ->setCache($this->connection->getCache())
+ ->setBaseDn($this->baseDn)
+ ->setModel($model);
+ }
+
+ /**
+ * Performs the specified query on the current LDAP connection.
+ *
+ * @param string $query
+ *
+ * @return Collection|array
+ */
+ public function query($query)
+ {
+ $start = microtime(true);
+
+ // Here we will create the execution callback. This allows us
+ // to only execute an LDAP request if caching is disabled
+ // or if no cache of the given query exists yet.
+ $callback = function () use ($query) {
+ return $this->parse($this->run($query));
+ };
+
+ $results = $this->getCachedResponse($query, $callback);
+
+ $this->logQuery($this, $this->type, $this->getElapsedTime($start));
+
+ return $this->process($results);
+ }
+
+ /**
+ * Paginates the current LDAP query.
+ *
+ * @param int $pageSize
+ * @param bool $isCritical
+ *
+ * @return Collection|array
+ */
+ public function paginate($pageSize = 1000, $isCritical = false)
+ {
+ $this->paginated = true;
+
+ $start = microtime(true);
+
+ $query = $this->getQuery();
+
+ // Here we will create the pagination callback. This allows us
+ // to only execute an LDAP request if caching is disabled
+ // or if no cache of the given query exists yet.
+ $callback = function () use ($query, $pageSize, $isCritical) {
+ return $this->runPaginate($query, $pageSize, $isCritical);
+ };
+
+ $pages = $this->getCachedResponse($query, $callback);
+
+ $this->logQuery($this, 'paginate', $this->getElapsedTime($start));
+
+ return $this->process($pages);
+ }
+
+ /**
+ * Runs the paginate operation with the given filter.
+ *
+ * @param string $filter
+ * @param int $perPage
+ * @param bool $isCritical
+ *
+ * @return array
+ */
+ protected function runPaginate($filter, $perPage, $isCritical)
+ {
+ return $this->connection->run(function (LdapInterface $ldap) use ($filter, $perPage, $isCritical) {
+ return (new Paginator($this, $filter, $perPage, $isCritical))->execute($ldap);
+ });
+ }
+
+ /**
+ * Chunk the results of a paginated LDAP query.
+ *
+ * @param int $pageSize
+ * @param Closure $callback
+ * @param bool $isCritical
+ *
+ * @return void
+ */
+ public function chunk($pageSize, Closure $callback, $isCritical = false)
+ {
+ $start = microtime(true);
+
+ $query = $this->getQuery();
+
+ foreach ($this->runChunk($query, $pageSize, $isCritical) as $chunk) {
+ $callback($this->process($chunk));
+ }
+
+ $this->logQuery($this, 'chunk', $this->getElapsedTime($start));
+ }
+
+ /**
+ * Runs the chunk operation with the given filter.
+ *
+ * @param string $filter
+ * @param int $perPage
+ * @param bool $isCritical
+ *
+ * @return array
+ */
+ protected function runChunk($filter, $perPage, $isCritical)
+ {
+ return $this->connection->run(function (LdapInterface $ldap) use ($filter, $perPage, $isCritical) {
+ return (new LazyPaginator($this, $filter, $perPage, $isCritical))->execute($ldap);
+ });
+ }
+
+ /**
+ * Processes and converts the given LDAP results into models.
+ *
+ * @param array $results
+ *
+ * @return array
+ */
+ protected function process(array $results)
+ {
+ unset($results['count']);
+
+ return $this->paginated ? $this->flattenPages($results) : $results;
+ }
+
+ /**
+ * Flattens LDAP paged results into a single array.
+ *
+ * @param array $pages
+ *
+ * @return array
+ */
+ protected function flattenPages(array $pages)
+ {
+ $records = [];
+
+ foreach ($pages as $page) {
+ unset($page['count']);
+
+ $records = array_merge($records, $page);
+ }
+
+ return $records;
+ }
+
+ /**
+ * Get the cached response or execute and cache the callback value.
+ *
+ * @param string $query
+ * @param Closure $callback
+ *
+ * @return mixed
+ */
+ protected function getCachedResponse($query, Closure $callback)
+ {
+ // If caching is enabled and we have a cache instance available,
+ // we will try to retrieve the cached results instead.
+ if ($this->caching && $this->cache) {
+ $key = $this->getCacheKey($query);
+
+ if ($this->flushCache) {
+ $this->cache->delete($key);
+ }
+
+ return $this->cache->remember($key, $this->cacheUntil, $callback);
+ }
+
+ // Otherwise, we will simply execute the callback.
+ return $callback();
+ }
+
+ /**
+ * Runs the query operation with the given filter.
+ *
+ * @param string $filter
+ *
+ * @return resource
+ */
+ public function run($filter)
+ {
+ return $this->connection->run(function (LdapInterface $ldap) use ($filter) {
+ // We will avoid setting the controls during any pagination
+ // requests as it will clear the cookie we need to send
+ // to the server upon retrieving every page.
+ if (! $this->paginated) {
+ // Before running the query, we will set the LDAP server controls. This
+ // allows the controls to be automatically reset upon each new query
+ // that is conducted on the same connection during each request.
+ $ldap->setOption(LDAP_OPT_SERVER_CONTROLS, $this->controls);
+ }
+
+ return $ldap->{$this->type}(
+ $this->dn ?? $this->baseDn,
+ $filter,
+ $this->getSelects(),
+ $onlyAttributes = false,
+ $this->limit
+ );
+ });
+ }
+
+ /**
+ * Parses the given LDAP resource by retrieving its entries.
+ *
+ * @param resource $resource
+ *
+ * @return array
+ */
+ public function parse($resource)
+ {
+ if (! $resource) {
+ return [];
+ }
+
+ return $this->connection->run(function (LdapInterface $ldap) use ($resource) {
+ $entries = $ldap->getEntries($resource);
+
+ // Free up memory.
+ if (is_resource($resource)) {
+ $ldap->freeResult($resource);
+ }
+
+ return $entries;
+ });
+ }
+
+ /**
+ * Returns the cache key.
+ *
+ * @param string $query
+ *
+ * @return string
+ */
+ protected function getCacheKey($query)
+ {
+ $host = $this->connection->getLdapConnection()->getHost();
+
+ $key = $host
+ .$this->type
+ .$this->getDn()
+ .$query
+ .implode($this->getSelects())
+ .$this->limit
+ .$this->paginated;
+
+ return md5($key);
+ }
+
+ /**
+ * Returns the first entry in a search result.
+ *
+ * @param array|string $columns
+ *
+ * @return Model|null
+ */
+ public function first($columns = ['*'])
+ {
+ return Arr::get($this->limit(1)->get($columns), 0);
+ }
+
+ /**
+ * Returns the first entry in a search result.
+ *
+ * If no entry is found, an exception is thrown.
+ *
+ * @param array|string $columns
+ *
+ * @throws ObjectNotFoundException
+ *
+ * @return Model|static
+ */
+ public function firstOrFail($columns = ['*'])
+ {
+ if (! $record = $this->first($columns)) {
+ $this->throwNotFoundException($this->getUnescapedQuery(), $this->dn);
+ }
+
+ return $record;
+ }
+
+ /**
+ * Throws a not found exception.
+ *
+ * @param string $query
+ * @param string $dn
+ *
+ * @throws ObjectNotFoundException
+ */
+ protected function throwNotFoundException($query, $dn)
+ {
+ throw ObjectNotFoundException::forQuery($query, $dn);
+ }
+
+ /**
+ * Finds a record by the specified attribute and value.
+ *
+ * @param string $attribute
+ * @param string $value
+ * @param array|string $columns
+ *
+ * @return Model|static|null
+ */
+ public function findBy($attribute, $value, $columns = ['*'])
+ {
+ try {
+ return $this->findByOrFail($attribute, $value, $columns);
+ } catch (ObjectNotFoundException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Finds a record by the specified attribute and value.
+ *
+ * If no record is found an exception is thrown.
+ *
+ * @param string $attribute
+ * @param string $value
+ * @param array|string $columns
+ *
+ * @throws ObjectNotFoundException
+ *
+ * @return Model
+ */
+ public function findByOrFail($attribute, $value, $columns = ['*'])
+ {
+ return $this->whereEquals($attribute, $value)->firstOrFail($columns);
+ }
+
+ /**
+ * Find many records by distinguished name.
+ *
+ * @param array $dns
+ * @param array $columns
+ *
+ * @return array|Collection
+ */
+ public function findMany($dns, $columns = ['*'])
+ {
+ if (empty($dns)) {
+ return $this->process([]);
+ }
+
+ $objects = [];
+
+ foreach ($dns as $dn) {
+ if (! is_null($object = $this->find($dn, $columns))) {
+ $objects[] = $object;
+ }
+ }
+
+ return $this->process($objects);
+ }
+
+ /**
+ * Finds many records by the specified attribute.
+ *
+ * @param string $attribute
+ * @param array $values
+ * @param array $columns
+ *
+ * @return Collection
+ */
+ public function findManyBy($attribute, array $values = [], $columns = ['*'])
+ {
+ $query = $this->select($columns);
+
+ foreach ($values as $value) {
+ $query->orWhere([$attribute => $value]);
+ }
+
+ return $query->get();
+ }
+
+ /**
+ * Finds a record by its distinguished name.
+ *
+ * @param string|array $dn
+ * @param array|string $columns
+ *
+ * @return Model|static|array|Collection|null
+ */
+ public function find($dn, $columns = ['*'])
+ {
+ if (is_array($dn)) {
+ return $this->findMany($dn, $columns);
+ }
+
+ try {
+ return $this->findOrFail($dn, $columns);
+ } catch (ObjectNotFoundException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Finds a record by its distinguished name.
+ *
+ * Fails upon no records returned.
+ *
+ * @param string $dn
+ * @param array|string $columns
+ *
+ * @throws ObjectNotFoundException
+ *
+ * @return Model|static
+ */
+ public function findOrFail($dn, $columns = ['*'])
+ {
+ return $this->setDn($dn)
+ ->read()
+ ->whereHas('objectclass')
+ ->firstOrFail($columns);
+ }
+
+ /**
+ * Adds the inserted fields to query on the current LDAP connection.
+ *
+ * @param array|string $columns
+ *
+ * @return $this
+ */
+ public function select($columns = ['*'])
+ {
+ $columns = is_array($columns) ? $columns : func_get_args();
+
+ if (! empty($columns)) {
+ $this->columns = $columns;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a new select column to the query.
+ *
+ * @param array|mixed $column
+ *
+ * @return $this
+ */
+ public function addSelect($column)
+ {
+ $column = is_array($column) ? $column : func_get_args();
+
+ $this->columns = array_merge((array) $this->columns, $column);
+
+ return $this;
+ }
+
+ /**
+ * Adds a raw filter to the current query.
+ *
+ * @param array|string $filters
+ *
+ * @return $this
+ */
+ public function rawFilter($filters = [])
+ {
+ $filters = is_array($filters) ? $filters : func_get_args();
+
+ foreach ($filters as $filter) {
+ $this->filters['raw'][] = $filter;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds a nested 'and' filter to the current query.
+ *
+ * @param Closure $closure
+ *
+ * @return $this
+ */
+ public function andFilter(Closure $closure)
+ {
+ $query = $this->newNestedInstance($closure);
+
+ return $this->rawFilter(
+ $this->grammar->compileAnd($query->getQuery())
+ );
+ }
+
+ /**
+ * Adds a nested 'or' filter to the current query.
+ *
+ * @param Closure $closure
+ *
+ * @return $this
+ */
+ public function orFilter(Closure $closure)
+ {
+ $query = $this->newNestedInstance($closure);
+
+ return $this->rawFilter(
+ $this->grammar->compileOr($query->getQuery())
+ );
+ }
+
+ /**
+ * Adds a nested 'not' filter to the current query.
+ *
+ * @param Closure $closure
+ *
+ * @return $this
+ */
+ public function notFilter(Closure $closure)
+ {
+ $query = $this->newNestedInstance($closure);
+
+ return $this->rawFilter(
+ $this->grammar->compileNot($query->getQuery())
+ );
+ }
+
+ /**
+ * Adds a where clause to the current query.
+ *
+ * @param string|array $field
+ * @param string $operator
+ * @param string $value
+ * @param string $boolean
+ * @param bool $raw
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function where($field, $operator = null, $value = null, $boolean = 'and', $raw = false)
+ {
+ if (is_array($field)) {
+ // If the field is an array, we will assume we have been
+ // provided with an array of key-value pairs and can
+ // add them each as their own seperate where clause.
+ return $this->addArrayOfWheres($field, $boolean, $raw);
+ }
+
+ // If we have been provided with two arguments not a "has" or
+ // "not has" operator, we'll assume the developer is creating
+ // an "equals" clause and set the proper operator in place.
+ if (func_num_args() === 2 && ! in_array($operator, ['*', '!*'])) {
+ [$value, $operator] = [$operator, '='];
+ }
+
+ if (! in_array($operator, $this->grammar->getOperators())) {
+ throw new InvalidArgumentException("Invalid LDAP filter operator [$operator]");
+ }
+
+ // We'll escape the value if raw isn't requested.
+ $value = $this->prepareWhereValue($field, $value, $raw);
+
+ $field = $this->escape($field)->both()->get();
+
+ $this->addFilter($boolean, compact('field', 'operator', 'value'));
+
+ return $this;
+ }
+
+ /**
+ * Prepare the value for being queried.
+ *
+ * @param string $field
+ * @param string $value
+ * @param bool $raw
+ *
+ * @return string
+ */
+ protected function prepareWhereValue($field, $value, $raw = false)
+ {
+ return $raw ? $value : $this->escape($value);
+ }
+
+ /**
+ * Adds a raw where clause to the current query.
+ *
+ * Values given to this method are not escaped.
+ *
+ * @param string|array $field
+ * @param string $operator
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function whereRaw($field, $operator = null, $value = null)
+ {
+ return $this->where($field, $operator, $value, 'and', true);
+ }
+
+ /**
+ * Adds a 'where equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function whereEquals($field, $value)
+ {
+ return $this->where($field, '=', $value);
+ }
+
+ /**
+ * Adds a 'where not equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function whereNotEquals($field, $value)
+ {
+ return $this->where($field, '!', $value);
+ }
+
+ /**
+ * Adds a 'where approximately equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function whereApproximatelyEquals($field, $value)
+ {
+ return $this->where($field, '~=', $value);
+ }
+
+ /**
+ * Adds a 'where has' clause to the current query.
+ *
+ * @param string $field
+ *
+ * @return $this
+ */
+ public function whereHas($field)
+ {
+ return $this->where($field, '*');
+ }
+
+ /**
+ * Adds a 'where not has' clause to the current query.
+ *
+ * @param string $field
+ *
+ * @return $this
+ */
+ public function whereNotHas($field)
+ {
+ return $this->where($field, '!*');
+ }
+
+ /**
+ * Adds a 'where contains' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function whereContains($field, $value)
+ {
+ return $this->where($field, 'contains', $value);
+ }
+
+ /**
+ * Adds a 'where contains' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function whereNotContains($field, $value)
+ {
+ return $this->where($field, 'not_contains', $value);
+ }
+
+ /**
+ * Query for entries that match any of the values provided for the given field.
+ *
+ * @param string $field
+ * @param array $values
+ *
+ * @return $this
+ */
+ public function whereIn($field, array $values)
+ {
+ return $this->orFilter(function (self $query) use ($field, $values) {
+ foreach ($values as $value) {
+ $query->whereEquals($field, $value);
+ }
+ });
+ }
+
+ /**
+ * Adds a 'between' clause to the current query.
+ *
+ * @param string $field
+ * @param array $values
+ *
+ * @return $this
+ */
+ public function whereBetween($field, array $values)
+ {
+ return $this->where([
+ [$field, '>=', $values[0]],
+ [$field, '<=', $values[1]],
+ ]);
+ }
+
+ /**
+ * Adds a 'where starts with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function whereStartsWith($field, $value)
+ {
+ return $this->where($field, 'starts_with', $value);
+ }
+
+ /**
+ * Adds a 'where *not* starts with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function whereNotStartsWith($field, $value)
+ {
+ return $this->where($field, 'not_starts_with', $value);
+ }
+
+ /**
+ * Adds a 'where ends with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function whereEndsWith($field, $value)
+ {
+ return $this->where($field, 'ends_with', $value);
+ }
+
+ /**
+ * Adds a 'where *not* ends with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function whereNotEndsWith($field, $value)
+ {
+ return $this->where($field, 'not_ends_with', $value);
+ }
+
+ /**
+ * Only include deleted models in the results.
+ *
+ * @return $this
+ */
+ public function whereDeleted()
+ {
+ return $this->withDeleted()->whereEquals('isDeleted', 'TRUE');
+ }
+
+ /**
+ * Set the LDAP control option to include deleted LDAP models.
+ *
+ * @return $this
+ */
+ public function withDeleted()
+ {
+ return $this->addControl(LdapInterface::OID_SERVER_SHOW_DELETED, $isCritical = true);
+ }
+
+ /**
+ * Add a server control to the query.
+ *
+ * @param string $oid
+ * @param bool $isCritical
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function addControl($oid, $isCritical = false, $value = null)
+ {
+ $this->controls[$oid] = compact('oid', 'isCritical', 'value');
+
+ return $this;
+ }
+
+ /**
+ * Determine if the server control exists on the query.
+ *
+ * @param string $oid
+ *
+ * @return bool
+ */
+ public function hasControl($oid)
+ {
+ return array_key_exists($oid, $this->controls);
+ }
+
+ /**
+ * Adds an 'or where' clause to the current query.
+ *
+ * @param array|string $field
+ * @param string|null $operator
+ * @param string|null $value
+ *
+ * @return $this
+ */
+ public function orWhere($field, $operator = null, $value = null)
+ {
+ return $this->where($field, $operator, $value, 'or');
+ }
+
+ /**
+ * Adds a raw or where clause to the current query.
+ *
+ * Values given to this method are not escaped.
+ *
+ * @param string $field
+ * @param string $operator
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function orWhereRaw($field, $operator = null, $value = null)
+ {
+ return $this->where($field, $operator, $value, 'or', true);
+ }
+
+ /**
+ * Adds an 'or where has' clause to the current query.
+ *
+ * @param string $field
+ *
+ * @return $this
+ */
+ public function orWhereHas($field)
+ {
+ return $this->orWhere($field, '*');
+ }
+
+ /**
+ * Adds a 'where not has' clause to the current query.
+ *
+ * @param string $field
+ *
+ * @return $this
+ */
+ public function orWhereNotHas($field)
+ {
+ return $this->orWhere($field, '!*');
+ }
+
+ /**
+ * Adds an 'or where equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function orWhereEquals($field, $value)
+ {
+ return $this->orWhere($field, '=', $value);
+ }
+
+ /**
+ * Adds an 'or where not equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function orWhereNotEquals($field, $value)
+ {
+ return $this->orWhere($field, '!', $value);
+ }
+
+ /**
+ * Adds a 'or where approximately equals' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function orWhereApproximatelyEquals($field, $value)
+ {
+ return $this->orWhere($field, '~=', $value);
+ }
+
+ /**
+ * Adds an 'or where contains' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function orWhereContains($field, $value)
+ {
+ return $this->orWhere($field, 'contains', $value);
+ }
+
+ /**
+ * Adds an 'or where *not* contains' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function orWhereNotContains($field, $value)
+ {
+ return $this->orWhere($field, 'not_contains', $value);
+ }
+
+ /**
+ * Adds an 'or where starts with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function orWhereStartsWith($field, $value)
+ {
+ return $this->orWhere($field, 'starts_with', $value);
+ }
+
+ /**
+ * Adds an 'or where *not* starts with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function orWhereNotStartsWith($field, $value)
+ {
+ return $this->orWhere($field, 'not_starts_with', $value);
+ }
+
+ /**
+ * Adds an 'or where ends with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function orWhereEndsWith($field, $value)
+ {
+ return $this->orWhere($field, 'ends_with', $value);
+ }
+
+ /**
+ * Adds an 'or where *not* ends with' clause to the current query.
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function orWhereNotEndsWith($field, $value)
+ {
+ return $this->orWhere($field, 'not_ends_with', $value);
+ }
+
+ /**
+ * Adds a filter binding onto the current query.
+ *
+ * @param string $type The type of filter to add.
+ * @param array $bindings The bindings of the filter.
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function addFilter($type, array $bindings)
+ {
+ if (! array_key_exists($type, $this->filters)) {
+ throw new InvalidArgumentException("Filter type: [$type] is invalid.");
+ }
+
+ // Each filter clause require key bindings to be set. We
+ // will validate this here to ensure all of them have
+ // been provided, or throw an exception otherwise.
+ if ($missing = $this->missingBindingKeys($bindings)) {
+ $keys = implode(', ', $missing);
+
+ throw new InvalidArgumentException("Invalid filter bindings. Missing: [$keys] keys.");
+ }
+
+ $this->filters[$type][] = $bindings;
+
+ return $this;
+ }
+
+ /**
+ * Extract any missing required binding keys.
+ *
+ * @param array $bindings
+ *
+ * @return array
+ */
+ protected function missingBindingKeys($bindings)
+ {
+ $required = array_flip(['field', 'operator', 'value']);
+
+ $existing = array_intersect_key($required, $bindings);
+
+ return array_keys(array_diff_key($required, $existing));
+ }
+
+ /**
+ * Get all the filters on the query.
+ *
+ * @return array
+ */
+ public function getFilters()
+ {
+ return $this->filters;
+ }
+
+ /**
+ * Clear the query filters.
+ *
+ * @return $this
+ */
+ public function clearFilters()
+ {
+ foreach (array_keys($this->filters) as $type) {
+ $this->filters[$type] = [];
+ }
+
+ return $this;
+ }
+
+ /**
+ * Determine if the query has attributes selected.
+ *
+ * @return bool
+ */
+ public function hasSelects()
+ {
+ return count($this->columns) > 0;
+ }
+
+ /**
+ * Get the attributes to select on the search.
+ *
+ * @return array
+ */
+ public function getSelects()
+ {
+ $selects = $this->columns ?? ['*'];
+
+ if (in_array('*', $selects)) {
+ return $selects;
+ }
+
+ if (in_array('objectclass', $selects)) {
+ return $selects;
+ }
+
+ // If the * character is not provided in the selected columns,
+ // we need to ensure we always select the object class, as
+ // this is used for constructing models properly.
+ $selects[] = 'objectclass';
+
+ return $selects;
+ }
+
+ /**
+ * Set the query to search on the base distinguished name.
+ *
+ * This will result in one record being returned.
+ *
+ * @return $this
+ */
+ public function read()
+ {
+ $this->type = 'read';
+
+ return $this;
+ }
+
+ /**
+ * Set the query to search one level on the base distinguished name.
+ *
+ * @return $this
+ */
+ public function listing()
+ {
+ $this->type = 'listing';
+
+ return $this;
+ }
+
+ /**
+ * Set the query to search the entire directory on the base distinguished name.
+ *
+ * @return $this
+ */
+ public function recursive()
+ {
+ $this->type = 'search';
+
+ return $this;
+ }
+
+ /**
+ * Whether to mark the current query as nested.
+ *
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function nested($nested = true)
+ {
+ $this->nested = (bool) $nested;
+
+ return $this;
+ }
+
+ /**
+ * Enables caching on the current query until the given date.
+ *
+ * If flushing is enabled, the query cache will be flushed and then re-cached.
+ *
+ * @param DateTimeInterface $until When to expire the query cache.
+ * @param bool $flush Whether to force-flush the query cache.
+ *
+ * @return $this
+ */
+ public function cache(DateTimeInterface $until = null, $flush = false)
+ {
+ $this->caching = true;
+ $this->cacheUntil = $until;
+ $this->flushCache = $flush;
+
+ return $this;
+ }
+
+ /**
+ * Determine if the query is nested.
+ *
+ * @return bool
+ */
+ public function isNested()
+ {
+ return $this->nested === true;
+ }
+
+ /**
+ * Determine whether the query is paginated.
+ *
+ * @return bool
+ */
+ public function isPaginated()
+ {
+ return $this->paginated;
+ }
+
+ /**
+ * Insert an entry into the directory.
+ *
+ * @param string $dn
+ * @param array $attributes
+ *
+ * @throws LdapRecordException
+ *
+ * @return bool
+ */
+ public function insert($dn, array $attributes)
+ {
+ if (empty($dn)) {
+ throw new LdapRecordException('A new LDAP object must have a distinguished name (dn).');
+ }
+
+ if (! array_key_exists('objectclass', $attributes)) {
+ throw new LdapRecordException(
+ 'A new LDAP object must contain at least one object class (objectclass) to be created.'
+ );
+ }
+
+ return $this->connection->run(function (LdapInterface $ldap) use ($dn, $attributes) {
+ return $ldap->add($dn, $attributes);
+ });
+ }
+
+ /**
+ * Create attributes on the entry in the directory.
+ *
+ * @param string $dn
+ * @param array $attributes
+ *
+ * @return bool
+ */
+ public function insertAttributes($dn, array $attributes)
+ {
+ return $this->connection->run(function (LdapInterface $ldap) use ($dn, $attributes) {
+ return $ldap->modAdd($dn, $attributes);
+ });
+ }
+
+ /**
+ * Update the entry with the given modifications.
+ *
+ * @param string $dn
+ * @param array $modifications
+ *
+ * @return bool
+ */
+ public function update($dn, array $modifications)
+ {
+ return $this->connection->run(function (LdapInterface $ldap) use ($dn, $modifications) {
+ return $ldap->modifyBatch($dn, $modifications);
+ });
+ }
+
+ /**
+ * Update an entries attribute in the directory.
+ *
+ * @param string $dn
+ * @param array $attributes
+ *
+ * @return bool
+ */
+ public function updateAttributes($dn, array $attributes)
+ {
+ return $this->connection->run(function (LdapInterface $ldap) use ($dn, $attributes) {
+ return $ldap->modReplace($dn, $attributes);
+ });
+ }
+
+ /**
+ * Delete an entry from the directory.
+ *
+ * @param string $dn
+ *
+ * @return bool
+ */
+ public function delete($dn)
+ {
+ return $this->connection->run(function (LdapInterface $ldap) use ($dn) {
+ return $ldap->delete($dn);
+ });
+ }
+
+ /**
+ * Delete attributes on the entry in the directory.
+ *
+ * @param string $dn
+ * @param array $attributes
+ *
+ * @return bool
+ */
+ public function deleteAttributes($dn, array $attributes)
+ {
+ return $this->connection->run(function (LdapInterface $ldap) use ($dn, $attributes) {
+ return $ldap->modDelete($dn, $attributes);
+ });
+ }
+
+ /**
+ * Rename an entry in the directory.
+ *
+ * @param string $dn
+ * @param string $rdn
+ * @param string $newParentDn
+ * @param bool $deleteOldRdn
+ *
+ * @return bool
+ */
+ public function rename($dn, $rdn, $newParentDn, $deleteOldRdn = true)
+ {
+ return $this->connection->run(function (LdapInterface $ldap) use ($dn, $rdn, $newParentDn, $deleteOldRdn) {
+ return $ldap->rename($dn, $rdn, $newParentDn, $deleteOldRdn);
+ });
+ }
+
+ /**
+ * Handle dynamic method calls on the query builder.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @throws BadMethodCallException
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ // If the beginning of the method being called contains
+ // 'where', we will assume a dynamic 'where' clause is
+ // being performed and pass the parameters to it.
+ if (substr($method, 0, 5) === 'where') {
+ return $this->dynamicWhere($method, $parameters);
+ }
+
+ throw new BadMethodCallException(sprintf(
+ 'Call to undefined method %s::%s()',
+ static::class,
+ $method
+ ));
+ }
+
+ /**
+ * Handles dynamic "where" clauses to the query.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return $this
+ */
+ public function dynamicWhere($method, $parameters)
+ {
+ $finder = substr($method, 5);
+
+ $segments = preg_split('/(And|Or)(?=[A-Z])/', $finder, -1, PREG_SPLIT_DELIM_CAPTURE);
+
+ // The connector variable will determine which connector will be used for the
+ // query condition. We will change it as we come across new boolean values
+ // in the dynamic method strings, which could contain a number of these.
+ $connector = 'and';
+
+ $index = 0;
+
+ foreach ($segments as $segment) {
+ // If the segment is not a boolean connector, we can assume it is a column's name
+ // and we will add it to the query as a new constraint as a where clause, then
+ // we can keep iterating through the dynamic method string's segments again.
+ if ($segment != 'And' && $segment != 'Or') {
+ $this->addDynamic($segment, $connector, $parameters, $index);
+
+ $index++;
+ }
+
+ // Otherwise, we will store the connector so we know how the next where clause we
+ // find in the query should be connected to the previous ones, meaning we will
+ // have the proper boolean connector to connect the next where clause found.
+ else {
+ $connector = $segment;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds an array of wheres to the current query.
+ *
+ * @param array $wheres
+ * @param string $boolean
+ * @param bool $raw
+ *
+ * @return $this
+ */
+ protected function addArrayOfWheres($wheres, $boolean, $raw)
+ {
+ foreach ($wheres as $key => $value) {
+ if (is_numeric($key) && is_array($value)) {
+ // If the key is numeric and the value is an array, we'll
+ // assume we've been given an array with conditionals.
+ [$field, $condition] = $value;
+
+ // Since a value is optional for some conditionals, we will
+ // try and retrieve the third parameter from the array,
+ // but is entirely optional.
+ $value = Arr::get($value, 2);
+
+ $this->where($field, $condition, $value, $boolean);
+ } else {
+ // If the value is not an array, we will assume an equals clause.
+ $this->where($key, '=', $value, $boolean, $raw);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a single dynamic where clause statement to the query.
+ *
+ * @param string $segment
+ * @param string $connector
+ * @param array $parameters
+ * @param int $index
+ *
+ * @return void
+ */
+ protected function addDynamic($segment, $connector, $parameters, $index)
+ {
+ // If no parameters were given to the dynamic where clause,
+ // we can assume a "has" attribute filter is being added.
+ if (count($parameters) === 0) {
+ $this->where(strtolower($segment), '*', null, strtolower($connector));
+ } else {
+ $this->where(strtolower($segment), '=', $parameters[$index], strtolower($connector));
+ }
+ }
+
+ /**
+ * Logs the given executed query information by firing its query event.
+ *
+ * @param Builder $query
+ * @param string $type
+ * @param null|float $time
+ *
+ * @return void
+ */
+ protected function logQuery($query, $type, $time = null)
+ {
+ $args = [$query, $time];
+
+ switch ($type) {
+ case 'listing':
+ $event = new Events\Listing(...$args);
+ break;
+ case 'read':
+ $event = new Events\Read(...$args);
+ break;
+ case 'chunk':
+ $event = new Events\Chunk(...$args);
+ break;
+ case 'paginate':
+ $event = new Events\Paginate(...$args);
+ break;
+ default:
+ $event = new Events\Search(...$args);
+ break;
+ }
+
+ $this->fireQueryEvent($event);
+ }
+
+ /**
+ * Fires the given query event.
+ *
+ * @param QueryExecuted $event
+ *
+ * @return void
+ */
+ protected function fireQueryEvent(QueryExecuted $event)
+ {
+ Container::getInstance()->getEventDispatcher()->fire($event);
+ }
+
+ /**
+ * Get the elapsed time since a given starting point.
+ *
+ * @param int $start
+ *
+ * @return float
+ */
+ protected function getElapsedTime($start)
+ {
+ return round((microtime(true) - $start) * 1000, 2);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Cache.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Cache.php
new file mode 100644
index 0000000..dfbf8cd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Cache.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace LdapRecord\Query;
+
+use Closure;
+use DateInterval;
+use DateTimeInterface;
+use Psr\SimpleCache\CacheInterface;
+
+class Cache
+{
+ use InteractsWithTime;
+
+ /**
+ * The cache driver.
+ *
+ * @var CacheInterface
+ */
+ protected $store;
+
+ /**
+ * Constructor.
+ *
+ * @param CacheInterface $store
+ */
+ public function __construct(CacheInterface $store)
+ {
+ $this->store = $store;
+ }
+
+ /**
+ * Get an item from the cache.
+ *
+ * @param string $key
+ *
+ * @return mixed
+ */
+ public function get($key)
+ {
+ return $this->store->get($key);
+ }
+
+ /**
+ * Store an item in the cache.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param DateTimeInterface|DateInterval|int|null $ttl
+ *
+ * @return bool
+ */
+ public function put($key, $value, $ttl = null)
+ {
+ $seconds = $this->secondsUntil($ttl);
+
+ if ($seconds <= 0) {
+ return $this->delete($key);
+ }
+
+ return $this->store->set($key, $value, $seconds);
+ }
+
+ /**
+ * Get an item from the cache, or execute the given Closure and store the result.
+ *
+ * @param string $key
+ * @param DateTimeInterface|DateInterval|int|null $ttl
+ * @param Closure $callback
+ *
+ * @return mixed
+ */
+ public function remember($key, $ttl, Closure $callback)
+ {
+ $value = $this->get($key);
+
+ if (! is_null($value)) {
+ return $value;
+ }
+
+ $this->put($key, $value = $callback(), $ttl);
+
+ return $value;
+ }
+
+ /**
+ * Delete an item from the cache.
+ *
+ * @param string $key
+ *
+ * @return bool
+ */
+ public function delete($key)
+ {
+ return $this->store->delete($key);
+ }
+
+ /**
+ * Get the underlying cache store.
+ *
+ * @return CacheInterface
+ */
+ public function store()
+ {
+ return $this->store;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Collection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Collection.php
new file mode 100644
index 0000000..a02146d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Collection.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace LdapRecord\Query;
+
+use LdapRecord\Models\Model;
+use Tightenco\Collect\Support\Collection as BaseCollection;
+
+class Collection extends BaseCollection
+{
+ /**
+ * @inheritdoc
+ */
+ protected function valueRetriever($value)
+ {
+ if ($this->useAsCallable($value)) {
+ return $value;
+ }
+
+ return function ($item) use ($value) {
+ return $item instanceof Model
+ ? $item->getFirstAttribute($value)
+ : data_get($item, $value);
+ };
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Chunk.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Chunk.php
new file mode 100644
index 0000000..3cd36d8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Chunk.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Query\Events;
+
+class Chunk extends QueryExecuted
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Listing.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Listing.php
new file mode 100644
index 0000000..2b88ad9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Listing.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Query\Events;
+
+class Listing extends QueryExecuted
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Paginate.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Paginate.php
new file mode 100644
index 0000000..6f8f262
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Paginate.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Query\Events;
+
+class Paginate extends QueryExecuted
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/QueryExecuted.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/QueryExecuted.php
new file mode 100644
index 0000000..f13ddeb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/QueryExecuted.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace LdapRecord\Query\Events;
+
+use LdapRecord\Query\Builder;
+
+class QueryExecuted
+{
+ /**
+ * The LDAP filter that was used for the query.
+ *
+ * @var string
+ */
+ protected $query;
+
+ /**
+ * The number of milliseconds it took to execute the query.
+ *
+ * @var float
+ */
+ protected $time;
+
+ /**
+ * Constructor.
+ *
+ * @param Builder $query
+ * @param null|float $time
+ */
+ public function __construct(Builder $query, $time = null)
+ {
+ $this->query = $query;
+ $this->time = $time;
+ }
+
+ /**
+ * Returns the LDAP filter that was used for the query.
+ *
+ * @return Builder
+ */
+ public function getQuery()
+ {
+ return $this->query;
+ }
+
+ /**
+ * Returns the number of milliseconds it took to execute the query.
+ *
+ * @return float|null
+ */
+ public function getTime()
+ {
+ return $this->time;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Read.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Read.php
new file mode 100644
index 0000000..510c4ca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Read.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Query\Events;
+
+class Read extends QueryExecuted
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Search.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Search.php
new file mode 100644
index 0000000..5132316
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Events/Search.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace LdapRecord\Query\Events;
+
+class Search extends QueryExecuted
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Grammar.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Grammar.php
new file mode 100644
index 0000000..3217173
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Grammar.php
@@ -0,0 +1,549 @@
+<?php
+
+namespace LdapRecord\Query;
+
+use UnexpectedValueException;
+
+class Grammar
+{
+ /**
+ * The query operators and their method names.
+ *
+ * @var array
+ */
+ public $operators = [
+ '*' => 'has',
+ '!*' => 'notHas',
+ '=' => 'equals',
+ '!' => 'doesNotEqual',
+ '!=' => 'doesNotEqual',
+ '>=' => 'greaterThanOrEquals',
+ '<=' => 'lessThanOrEquals',
+ '~=' => 'approximatelyEquals',
+ 'starts_with' => 'startsWith',
+ 'not_starts_with' => 'notStartsWith',
+ 'ends_with' => 'endsWith',
+ 'not_ends_with' => 'notEndsWith',
+ 'contains' => 'contains',
+ 'not_contains' => 'notContains',
+ ];
+
+ /**
+ * The query wrapper.
+ *
+ * @var string|null
+ */
+ protected $wrapper;
+
+ /**
+ * Get all the available operators.
+ *
+ * @return array
+ */
+ public function getOperators()
+ {
+ return array_keys($this->operators);
+ }
+
+ /**
+ * Wraps a query string in brackets.
+ *
+ * Produces: (query)
+ *
+ * @param string $query
+ * @param string $prefix
+ * @param string $suffix
+ *
+ * @return string
+ */
+ public function wrap($query, $prefix = '(', $suffix = ')')
+ {
+ return $prefix.$query.$suffix;
+ }
+
+ /**
+ * Compiles the Builder instance into an LDAP query string.
+ *
+ * @param Builder $query
+ *
+ * @return string
+ */
+ public function compile(Builder $query)
+ {
+ if ($this->queryMustBeWrapped($query)) {
+ $this->wrapper = 'and';
+ }
+
+ $filter = $this->compileRaws($query)
+ .$this->compileWheres($query)
+ .$this->compileOrWheres($query);
+
+ switch ($this->wrapper) {
+ case 'and':
+ return $this->compileAnd($filter);
+ case 'or':
+ return $this->compileOr($filter);
+ default:
+ return $filter;
+ }
+ }
+
+ /**
+ * Determine if the query must be wrapped in an encapsulating statement.
+ *
+ * @param Builder $query
+ *
+ * @return bool
+ */
+ protected function queryMustBeWrapped(Builder $query)
+ {
+ return ! $query->isNested() && $this->hasMultipleFilters($query);
+ }
+
+ /**
+ * Assembles all of the "raw" filters on the query.
+ *
+ * @param Builder $builder
+ *
+ * @return string
+ */
+ protected function compileRaws(Builder $builder)
+ {
+ return $this->concatenate($builder->filters['raw']);
+ }
+
+ /**
+ * Assembles all where clauses in the current wheres property.
+ *
+ * @param Builder $builder
+ * @param string $type
+ *
+ * @return string
+ */
+ protected function compileWheres(Builder $builder, $type = 'and')
+ {
+ $filter = '';
+
+ foreach ($builder->filters[$type] as $where) {
+ $filter .= $this->compileWhere($where);
+ }
+
+ return $filter;
+ }
+
+ /**
+ * Assembles all or where clauses in the current orWheres property.
+ *
+ * @param Builder $query
+ *
+ * @return string
+ */
+ protected function compileOrWheres(Builder $query)
+ {
+ $filter = $this->compileWheres($query, 'or');
+
+ if (! $this->hasMultipleFilters($query)) {
+ return $filter;
+ }
+
+ // Here we will detect whether the entire query can be
+ // wrapped inside of an "or" statement by checking
+ // how many filter statements exist for each type.
+ if ($this->queryCanBeWrappedInSingleOrStatement($query)) {
+ $this->wrapper = 'or';
+ } else {
+ $filter = $this->compileOr($filter);
+ }
+
+ return $filter;
+ }
+
+ /**
+ * Determine if the query can be wrapped in a single or statement.
+ *
+ * @param Builder $query
+ *
+ * @return bool
+ */
+ protected function queryCanBeWrappedInSingleOrStatement(Builder $query)
+ {
+ return $this->has($query, 'or', '>=', 1) &&
+ $this->has($query, 'and', '<=', 1) &&
+ $this->has($query, 'raw', '=', 0);
+ }
+
+ /**
+ * Concatenates filters into a single string.
+ *
+ * @param array $bindings
+ *
+ * @return string
+ */
+ public function concatenate(array $bindings = [])
+ {
+ // Filter out empty query segments.
+ return implode(
+ array_filter($bindings, [$this, 'bindingValueIsNotEmpty'])
+ );
+ }
+
+ /**
+ * Determine if the binding value is not empty.
+ *
+ * @param string $value
+ *
+ * @return bool
+ */
+ protected function bindingValueIsNotEmpty($value)
+ {
+ return ! empty($value);
+ }
+
+ /**
+ * Determine if the query is using multiple filters.
+ *
+ * @param Builder $query
+ *
+ * @return bool
+ */
+ protected function hasMultipleFilters(Builder $query)
+ {
+ return $this->has($query, ['and', 'or', 'raw'], '>', 1);
+ }
+
+ /**
+ * Determine if the query contains the given filter statement type.
+ *
+ * @param Builder $query
+ * @param string|array $type
+ * @param string $operator
+ * @param int $count
+ *
+ * @return bool
+ */
+ protected function has(Builder $query, $type, $operator = '>=', $count = 1)
+ {
+ $types = (array) $type;
+
+ $filters = 0;
+
+ foreach ($types as $type) {
+ $filters += count($query->filters[$type]);
+ }
+
+ switch ($operator) {
+ case '>':
+ return $filters > $count;
+ case '>=':
+ return $filters >= $count;
+ case '<':
+ return $filters < $count;
+ case '<=':
+ return $filters <= $count;
+ default:
+ return $filters == $count;
+ }
+ }
+
+ /**
+ * Returns a query string for equals.
+ *
+ * Produces: (field=value)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileEquals($field, $value)
+ {
+ return $this->wrap($field.'='.$value);
+ }
+
+ /**
+ * Returns a query string for does not equal.
+ *
+ * Produces: (!(field=value))
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileDoesNotEqual($field, $value)
+ {
+ return $this->compileNot(
+ $this->compileEquals($field, $value)
+ );
+ }
+
+ /**
+ * Alias for does not equal operator (!=) operator.
+ *
+ * Produces: (!(field=value))
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileDoesNotEqualAlias($field, $value)
+ {
+ return $this->compileDoesNotEqual($field, $value);
+ }
+
+ /**
+ * Returns a query string for greater than or equals.
+ *
+ * Produces: (field>=value)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileGreaterThanOrEquals($field, $value)
+ {
+ return $this->wrap("$field>=$value");
+ }
+
+ /**
+ * Returns a query string for less than or equals.
+ *
+ * Produces: (field<=value)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileLessThanOrEquals($field, $value)
+ {
+ return $this->wrap("$field<=$value");
+ }
+
+ /**
+ * Returns a query string for approximately equals.
+ *
+ * Produces: (field~=value)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileApproximatelyEquals($field, $value)
+ {
+ return $this->wrap("$field~=$value");
+ }
+
+ /**
+ * Returns a query string for starts with.
+ *
+ * Produces: (field=value*)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileStartsWith($field, $value)
+ {
+ return $this->wrap("$field=$value*");
+ }
+
+ /**
+ * Returns a query string for does not start with.
+ *
+ * Produces: (!(field=*value))
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileNotStartsWith($field, $value)
+ {
+ return $this->compileNot(
+ $this->compileStartsWith($field, $value)
+ );
+ }
+
+ /**
+ * Returns a query string for ends with.
+ *
+ * Produces: (field=*value)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileEndsWith($field, $value)
+ {
+ return $this->wrap("$field=*$value");
+ }
+
+ /**
+ * Returns a query string for does not end with.
+ *
+ * Produces: (!(field=value*))
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileNotEndsWith($field, $value)
+ {
+ return $this->compileNot($this->compileEndsWith($field, $value));
+ }
+
+ /**
+ * Returns a query string for contains.
+ *
+ * Produces: (field=*value*)
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileContains($field, $value)
+ {
+ return $this->wrap("$field=*$value*");
+ }
+
+ /**
+ * Returns a query string for does not contain.
+ *
+ * Produces: (!(field=*value*))
+ *
+ * @param string $field
+ * @param string $value
+ *
+ * @return string
+ */
+ public function compileNotContains($field, $value)
+ {
+ return $this->compileNot(
+ $this->compileContains($field, $value)
+ );
+ }
+
+ /**
+ * Returns a query string for a where has.
+ *
+ * Produces: (field=*)
+ *
+ * @param string $field
+ *
+ * @return string
+ */
+ public function compileHas($field)
+ {
+ return $this->wrap("$field=*");
+ }
+
+ /**
+ * Returns a query string for a where does not have.
+ *
+ * Produces: (!(field=*))
+ *
+ * @param string $field
+ *
+ * @return string
+ */
+ public function compileNotHas($field)
+ {
+ return $this->compileNot(
+ $this->compileHas($field)
+ );
+ }
+
+ /**
+ * Wraps the inserted query inside an AND operator.
+ *
+ * Produces: (&query)
+ *
+ * @param string $query
+ *
+ * @return string
+ */
+ public function compileAnd($query)
+ {
+ return $query ? $this->wrap($query, '(&') : '';
+ }
+
+ /**
+ * Wraps the inserted query inside an OR operator.
+ *
+ * Produces: (|query)
+ *
+ * @param string $query
+ *
+ * @return string
+ */
+ public function compileOr($query)
+ {
+ return $query ? $this->wrap($query, '(|') : '';
+ }
+
+ /**
+ * Wraps the inserted query inside an NOT operator.
+ *
+ * @param string $query
+ *
+ * @return string
+ */
+ public function compileNot($query)
+ {
+ return $query ? $this->wrap($query, '(!') : '';
+ }
+
+ /**
+ * Assembles a single where query.
+ *
+ * @param array $where
+ *
+ * @throws UnexpectedValueException
+ *
+ * @return string
+ */
+ protected function compileWhere(array $where)
+ {
+ $method = $this->makeCompileMethod($where['operator']);
+
+ return $this->{$method}($where['field'], $where['value']);
+ }
+
+ /**
+ * Make the compile method name for the operator.
+ *
+ * @param string $operator
+ *
+ * @throws UnexpectedValueException
+ *
+ * @return string
+ */
+ protected function makeCompileMethod($operator)
+ {
+ if (! $this->operatorExists($operator)) {
+ throw new UnexpectedValueException("Invalid LDAP filter operator ['$operator']");
+ }
+
+ return 'compile'.ucfirst($this->operators[$operator]);
+ }
+
+ /**
+ * Determine if the operator exists.
+ *
+ * @param string $operator
+ *
+ * @return bool
+ */
+ protected function operatorExists($operator)
+ {
+ return array_key_exists($operator, $this->operators);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/InteractsWithTime.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/InteractsWithTime.php
new file mode 100644
index 0000000..1562ec0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/InteractsWithTime.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace LdapRecord\Query;
+
+use Carbon\Carbon;
+use DateInterval;
+use DateTimeInterface;
+
+/**
+ * @author Taylor Otwell
+ *
+ * @see https://laravel.com
+ */
+trait InteractsWithTime
+{
+ /**
+ * Get the number of seconds until the given DateTime.
+ *
+ * @param DateTimeInterface|DateInterval|int $delay
+ *
+ * @return int
+ */
+ protected function secondsUntil($delay)
+ {
+ $delay = $this->parseDateInterval($delay);
+
+ return $delay instanceof DateTimeInterface
+ ? max(0, $delay->getTimestamp() - $this->currentTime())
+ : (int) $delay;
+ }
+
+ /**
+ * Get the "available at" UNIX timestamp.
+ *
+ * @param DateTimeInterface|DateInterval|int $delay
+ *
+ * @return int
+ */
+ protected function availableAt($delay = 0)
+ {
+ $delay = $this->parseDateInterval($delay);
+
+ return $delay instanceof DateTimeInterface
+ ? $delay->getTimestamp()
+ : Carbon::now()->addRealSeconds($delay)->getTimestamp();
+ }
+
+ /**
+ * If the given value is an interval, convert it to a DateTime instance.
+ *
+ * @param DateTimeInterface|DateInterval|int $delay
+ *
+ * @return DateTimeInterface|int
+ */
+ protected function parseDateInterval($delay)
+ {
+ if ($delay instanceof DateInterval) {
+ $delay = Carbon::now()->add($delay);
+ }
+
+ return $delay;
+ }
+
+ /**
+ * Get the current system time as a UNIX timestamp.
+ *
+ * @return int
+ */
+ protected function currentTime()
+ {
+ return Carbon::now()->getTimestamp();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/ActiveDirectoryBuilder.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/ActiveDirectoryBuilder.php
new file mode 100644
index 0000000..8923015
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/ActiveDirectoryBuilder.php
@@ -0,0 +1,247 @@
+<?php
+
+namespace LdapRecord\Query\Model;
+
+use Closure;
+use LdapRecord\LdapInterface;
+use LdapRecord\Models\Attributes\AccountControl;
+use LdapRecord\Models\ModelNotFoundException;
+
+class ActiveDirectoryBuilder extends Builder
+{
+ /**
+ * Finds a record by its Object SID.
+ *
+ * @param string $sid
+ * @param array|string $columns
+ *
+ * @return \LdapRecord\Models\ActiveDirectory\Entry|static|null
+ */
+ public function findBySid($sid, $columns = [])
+ {
+ try {
+ return $this->findBySidOrFail($sid, $columns);
+ } catch (ModelNotFoundException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Finds a record by its Object SID.
+ *
+ * Fails upon no records returned.
+ *
+ * @param string $sid
+ * @param array|string $columns
+ *
+ * @throws ModelNotFoundException
+ *
+ * @return \LdapRecord\Models\ActiveDirectory\Entry|static
+ */
+ public function findBySidOrFail($sid, $columns = [])
+ {
+ return $this->findByOrFail('objectsid', $sid, $columns);
+ }
+
+ /**
+ * Adds a enabled filter to the current query.
+ *
+ * @return $this
+ */
+ public function whereEnabled()
+ {
+ return $this->notFilter(function ($query) {
+ return $query->whereDisabled();
+ });
+ }
+
+ /**
+ * Adds a disabled filter to the current query.
+ *
+ * @return $this
+ */
+ public function whereDisabled()
+ {
+ return $this->rawFilter(
+ (new AccountControl())->accountIsDisabled()->filter()
+ );
+ }
+
+ /**
+ * Adds a 'where member' filter to the current query.
+ *
+ * @param string $dn
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function whereMember($dn, $nested = false)
+ {
+ return $this->nestedMatchQuery(function ($attribute) use ($dn) {
+ return $this->whereEquals($attribute, $dn);
+ }, 'member', $nested);
+ }
+
+ /**
+ * Adds an 'or where member' filter to the current query.
+ *
+ * @param string $dn
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function orWhereMember($dn, $nested = false)
+ {
+ return $this->nestedMatchQuery(function ($attribute) use ($dn) {
+ return $this->orWhereEquals($attribute, $dn);
+ }, 'member', $nested);
+ }
+
+ /**
+ * Adds a 'where member of' filter to the current query.
+ *
+ * @param string $dn
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function whereMemberOf($dn, $nested = false)
+ {
+ return $this->nestedMatchQuery(function ($attribute) use ($dn) {
+ return $this->whereEquals($attribute, $dn);
+ }, 'memberof', $nested);
+ }
+
+ /**
+ * Adds a 'where not member of' filter to the current query.
+ *
+ * @param string $dn
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function whereNotMemberof($dn, $nested = false)
+ {
+ return $this->nestedMatchQuery(function ($attribute) use ($dn) {
+ return $this->whereNotEquals($attribute, $dn);
+ }, 'memberof', $nested);
+ }
+
+ /**
+ * Adds an 'or where member of' filter to the current query.
+ *
+ * @param string $dn
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function orWhereMemberOf($dn, $nested = false)
+ {
+ return $this->nestedMatchQuery(function ($attribute) use ($dn) {
+ return $this->orWhereEquals($attribute, $dn);
+ }, 'memberof', $nested);
+ }
+
+ /**
+ * Adds a 'or where not member of' filter to the current query.
+ *
+ * @param string $dn
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function orWhereNotMemberof($dn, $nested = false)
+ {
+ return $this->nestedMatchQuery(function ($attribute) use ($dn) {
+ return $this->orWhereNotEquals($attribute, $dn);
+ }, 'memberof', $nested);
+ }
+
+ /**
+ * Adds a 'where manager' filter to the current query.
+ *
+ * @param string $dn
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function whereManager($dn, $nested = false)
+ {
+ return $this->nestedMatchQuery(function ($attribute) use ($dn) {
+ return $this->whereEquals($attribute, $dn);
+ }, 'manager', $nested);
+ }
+
+ /**
+ * Adds a 'where not manager' filter to the current query.
+ *
+ * @param string $dn
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function whereNotManager($dn, $nested = false)
+ {
+ return $this->nestedMatchQuery(function ($attribute) use ($dn) {
+ return $this->whereNotEquals($attribute, $dn);
+ }, 'manager', $nested);
+ }
+
+ /**
+ * Adds an 'or where manager' filter to the current query.
+ *
+ * @param string $dn
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function orWhereManager($dn, $nested = false)
+ {
+ return $this->nestedMatchQuery(function ($attribute) use ($dn) {
+ return $this->orWhereEquals($attribute, $dn);
+ }, 'manager', $nested);
+ }
+
+ /**
+ * Adds an 'or where not manager' filter to the current query.
+ *
+ * @param string $dn
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ public function orWhereNotManager($dn, $nested = false)
+ {
+ return $this->nestedMatchQuery(function ($attribute) use ($dn) {
+ return $this->orWhereNotEquals($attribute, $dn);
+ }, 'manager', $nested);
+ }
+
+ /**
+ * Execute the callback with a nested match attribute.
+ *
+ * @param Closure $callback
+ * @param string $attribute
+ * @param bool $nested
+ *
+ * @return $this
+ */
+ protected function nestedMatchQuery(Closure $callback, $attribute, $nested = false)
+ {
+ return $callback(
+ $nested ? $this->makeNestedMatchAttribute($attribute) : $attribute
+ );
+ }
+
+ /**
+ * Make a "nested match" filter attribute for querying descendants.
+ *
+ * @param string $attribute
+ *
+ * @return string
+ */
+ protected function makeNestedMatchAttribute($attribute)
+ {
+ return sprintf('%s:%s:', $attribute, LdapInterface::OID_MATCHING_RULE_IN_CHAIN);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/Builder.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/Builder.php
new file mode 100644
index 0000000..eed5e91
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/Builder.php
@@ -0,0 +1,446 @@
+<?php
+
+namespace LdapRecord\Query\Model;
+
+use Closure;
+use DateTime;
+use LdapRecord\Models\Model;
+use LdapRecord\Models\ModelNotFoundException;
+use LdapRecord\Models\Scope;
+use LdapRecord\Models\Types\ActiveDirectory;
+use LdapRecord\Query\Builder as BaseBuilder;
+use LdapRecord\Utilities;
+
+class Builder extends BaseBuilder
+{
+ /**
+ * The model being queried.
+ *
+ * @var Model
+ */
+ protected $model;
+
+ /**
+ * The global scopes to be applied.
+ *
+ * @var array
+ */
+ protected $scopes = [];
+
+ /**
+ * The removed global scopes.
+ *
+ * @var array
+ */
+ protected $removedScopes = [];
+
+ /**
+ * The applied global scopes.
+ *
+ * @var array
+ */
+ protected $appliedScopes = [];
+
+ /**
+ * Dynamically handle calls into the query instance.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ if (method_exists($this->model, $scope = 'scope'.ucfirst($method))) {
+ return $this->callScope([$this->model, $scope], $parameters);
+ }
+
+ return parent::__call($method, $parameters);
+ }
+
+ /**
+ * Apply the given scope on the current builder instance.
+ *
+ * @param callable $scope
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ protected function callScope(callable $scope, $parameters = [])
+ {
+ array_unshift($parameters, $this);
+
+ return $scope(...array_values($parameters)) ?? $this;
+ }
+
+ /**
+ * Get the attributes to select on the search.
+ *
+ * @return array
+ */
+ public function getSelects()
+ {
+ // Here we will ensure the models GUID attribute is always
+ // selected. In some LDAP directories, the attribute is
+ // virtual and must be requested for specifically.
+ return array_values(array_unique(
+ array_merge([$this->model->getGuidKey()], parent::getSelects())
+ ));
+ }
+
+ /**
+ * Set the model instance for the model being queried.
+ *
+ * @param Model $model
+ *
+ * @return $this
+ */
+ public function setModel(Model $model)
+ {
+ $this->model = $model;
+
+ return $this;
+ }
+
+ /**
+ * Returns the model being queried for.
+ *
+ * @return Model
+ */
+ public function getModel()
+ {
+ return $this->model;
+ }
+
+ /**
+ * Get a new model query builder instance.
+ *
+ * @param string|null $baseDn
+ *
+ * @return static
+ */
+ public function newInstance($baseDn = null)
+ {
+ return parent::newInstance($baseDn)->model($this->model);
+ }
+
+ /**
+ * Finds a model by its distinguished name.
+ *
+ * @param array|string $dn
+ * @param array|string|string[] $columns
+ *
+ * @return Model|\LdapRecord\Query\Collection|static|null
+ */
+ public function find($dn, $columns = ['*'])
+ {
+ return $this->afterScopes(function () use ($dn, $columns) {
+ return parent::find($dn, $columns);
+ });
+ }
+
+ /**
+ * Finds a record using ambiguous name resolution.
+ *
+ * @param string|array $value
+ * @param array|string $columns
+ *
+ * @return Model|\LdapRecord\Query\Collection|static|null
+ */
+ public function findByAnr($value, $columns = ['*'])
+ {
+ if (is_array($value)) {
+ return $this->findManyByAnr($value, $columns);
+ }
+
+ // If the model is not compatible with ANR filters,
+ // we must construct an equivalent filter that
+ // the current LDAP server does support.
+ if (! $this->modelIsCompatibleWithAnr()) {
+ return $this->prepareAnrEquivalentQuery($value)->first($columns);
+ }
+
+ return $this->findBy('anr', $value, $columns);
+ }
+
+ /**
+ * Determine if the current model is compatible with ANR filters.
+ *
+ * @return bool
+ */
+ protected function modelIsCompatibleWithAnr()
+ {
+ return $this->model instanceof ActiveDirectory;
+ }
+
+ /**
+ * Finds a record using ambiguous name resolution.
+ *
+ * If a record is not found, an exception is thrown.
+ *
+ * @param string $value
+ * @param array|string $columns
+ *
+ * @throws ModelNotFoundException
+ *
+ * @return Model
+ */
+ public function findByAnrOrFail($value, $columns = ['*'])
+ {
+ if (! $entry = $this->findByAnr($value, $columns)) {
+ $this->throwNotFoundException($this->getUnescapedQuery(), $this->dn);
+ }
+
+ return $entry;
+ }
+
+ /**
+ * Throws a not found exception.
+ *
+ * @param string $query
+ * @param string $dn
+ *
+ * @throws ModelNotFoundException
+ */
+ protected function throwNotFoundException($query, $dn)
+ {
+ throw ModelNotFoundException::forQuery($query, $dn);
+ }
+
+ /**
+ * Finds multiple records using ambiguous name resolution.
+ *
+ * @param array $values
+ * @param array $columns
+ *
+ * @return \LdapRecord\Query\Collection
+ */
+ public function findManyByAnr(array $values = [], $columns = ['*'])
+ {
+ $this->select($columns);
+
+ if (! $this->modelIsCompatibleWithAnr()) {
+ foreach ($values as $value) {
+ $this->prepareAnrEquivalentQuery($value);
+ }
+
+ return $this->get($columns);
+ }
+
+ return $this->findManyBy('anr', $values);
+ }
+
+ /**
+ * Creates an ANR equivalent query for LDAP distributions that do not support ANR.
+ *
+ * @param string $value
+ *
+ * @return $this
+ */
+ protected function prepareAnrEquivalentQuery($value)
+ {
+ return $this->orFilter(function (self $query) use ($value) {
+ foreach ($this->model->getAnrAttributes() as $attribute) {
+ $query->whereEquals($attribute, $value);
+ }
+ });
+ }
+
+ /**
+ * Finds a record by its string GUID.
+ *
+ * @param string $guid
+ * @param array|string $columns
+ *
+ * @return Model|static|null
+ */
+ public function findByGuid($guid, $columns = ['*'])
+ {
+ try {
+ return $this->findByGuidOrFail($guid, $columns);
+ } catch (ModelNotFoundException $e) {
+ return;
+ }
+ }
+
+ /**
+ * Finds a record by its string GUID.
+ *
+ * Fails upon no records returned.
+ *
+ * @param string $guid
+ * @param array|string $columns
+ *
+ * @throws ModelNotFoundException
+ *
+ * @return Model|static
+ */
+ public function findByGuidOrFail($guid, $columns = ['*'])
+ {
+ if ($this->model instanceof ActiveDirectory) {
+ $guid = Utilities::stringGuidToHex($guid);
+ }
+
+ return $this->whereRaw([
+ $this->model->getGuidKey() => $guid,
+ ])->firstOrFail($columns);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getQuery()
+ {
+ return $this->afterScopes(function () {
+ return parent::getQuery();
+ });
+ }
+
+ /**
+ * Apply the query scopes and execute the callback.
+ *
+ * @param Closure $callback
+ *
+ * @return mixed
+ */
+ protected function afterScopes(Closure $callback)
+ {
+ $this->applyScopes();
+
+ return $callback();
+ }
+
+ /**
+ * Apply the global query scopes.
+ *
+ * @return $this
+ */
+ public function applyScopes()
+ {
+ if (! $this->scopes) {
+ return $this;
+ }
+
+ foreach ($this->scopes as $identifier => $scope) {
+ if (isset($this->appliedScopes[$identifier])) {
+ continue;
+ }
+
+ $scope instanceof Scope
+ ? $scope->apply($this, $this->getModel())
+ : $scope($this);
+
+ $this->appliedScopes[$identifier] = $scope;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Register a new global scope.
+ *
+ * @param string $identifier
+ * @param Scope|\Closure $scope
+ *
+ * @return $this
+ */
+ public function withGlobalScope($identifier, $scope)
+ {
+ $this->scopes[$identifier] = $scope;
+
+ return $this;
+ }
+
+ /**
+ * Remove a registered global scope.
+ *
+ * @param Scope|string $scope
+ *
+ * @return $this
+ */
+ public function withoutGlobalScope($scope)
+ {
+ if (! is_string($scope)) {
+ $scope = get_class($scope);
+ }
+
+ unset($this->scopes[$scope]);
+
+ $this->removedScopes[] = $scope;
+
+ return $this;
+ }
+
+ /**
+ * Remove all or passed registered global scopes.
+ *
+ * @param array|null $scopes
+ *
+ * @return $this
+ */
+ public function withoutGlobalScopes(array $scopes = null)
+ {
+ if (! is_array($scopes)) {
+ $scopes = array_keys($this->scopes);
+ }
+
+ foreach ($scopes as $scope) {
+ $this->withoutGlobalScope($scope);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get an array of global scopes that were removed from the query.
+ *
+ * @return array
+ */
+ public function removedScopes()
+ {
+ return $this->removedScopes;
+ }
+
+ /**
+ * Get an array of the global scopes that were applied to the query.
+ *
+ * @return array
+ */
+ public function appliedScopes()
+ {
+ return $this->appliedScopes;
+ }
+
+ /**
+ * Processes and converts the given LDAP results into models.
+ *
+ * @param array $results
+ *
+ * @return \LdapRecord\Query\Collection
+ */
+ protected function process(array $results)
+ {
+ return $this->model->hydrate(parent::process($results));
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function prepareWhereValue($field, $value, $raw = false)
+ {
+ if ($value instanceof DateTime) {
+ $field = $this->model->normalizeAttributeKey($field);
+
+ if (! $this->model->isDateAttribute($field)) {
+ throw new \UnexpectedValueException(
+ "Cannot convert field [$field] to an LDAP timestamp. You must add this field as a model date."
+ .' Refer to https://ldaprecord.com/docs/model-mutators/#date-mutators'
+ );
+ }
+
+ $value = $this->model->fromDateTime($this->model->getDates()[$field], $value);
+ }
+
+ return parent::prepareWhereValue($field, $value, $raw);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/FreeIpaBuilder.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/FreeIpaBuilder.php
new file mode 100644
index 0000000..5e3d43f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/FreeIpaBuilder.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace LdapRecord\Query\Model;
+
+class FreeIpaBuilder extends Builder
+{
+ /**
+ * Adds a enabled filter to the current query.
+ *
+ * @return $this
+ */
+ public function whereEnabled()
+ {
+ return $this->rawFilter('(!(pwdAccountLockedTime=*))');
+ }
+
+ /**
+ * Adds a disabled filter to the current query.
+ *
+ * @return $this
+ */
+ public function whereDisabled()
+ {
+ return $this->rawFilter('(pwdAccountLockedTime=*)');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/OpenLdapBuilder.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/OpenLdapBuilder.php
new file mode 100644
index 0000000..dd41344
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Model/OpenLdapBuilder.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace LdapRecord\Query\Model;
+
+class OpenLdapBuilder extends Builder
+{
+ /**
+ * Adds a enabled filter to the current query.
+ *
+ * @return $this
+ */
+ public function whereEnabled()
+ {
+ return $this->rawFilter('(!(pwdAccountLockedTime=*))');
+ }
+
+ /**
+ * Adds a disabled filter to the current query.
+ *
+ * @return $this
+ */
+ public function whereDisabled()
+ {
+ return $this->rawFilter('(pwdAccountLockedTime=*)');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/ObjectNotFoundException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/ObjectNotFoundException.php
new file mode 100644
index 0000000..b2dec28
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/ObjectNotFoundException.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace LdapRecord\Query;
+
+use LdapRecord\LdapRecordException;
+
+class ObjectNotFoundException extends LdapRecordException
+{
+ /**
+ * The query filter that was used.
+ *
+ * @var string
+ */
+ protected $query;
+
+ /**
+ * The base DN of the query that was used.
+ *
+ * @var string
+ */
+ protected $baseDn;
+
+ /**
+ * Create a new exception for the executed filter.
+ *
+ * @param string $query
+ * @param null $baseDn
+ *
+ * @return static
+ */
+ public static function forQuery($query, $baseDn = null)
+ {
+ return (new static())->setQuery($query, $baseDn);
+ }
+
+ /**
+ * Set the query that was used.
+ *
+ * @param string $query
+ * @param string|null $baseDn
+ *
+ * @return $this
+ */
+ public function setQuery($query, $baseDn = null)
+ {
+ $this->query = $query;
+ $this->baseDn = $baseDn;
+ $this->message = "No LDAP query results for filter: [$query] in: [$baseDn]";
+
+ return $this;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/AbstractPaginator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/AbstractPaginator.php
new file mode 100644
index 0000000..3dfd3f1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/AbstractPaginator.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace LdapRecord\Query\Pagination;
+
+use LdapRecord\LdapInterface;
+use LdapRecord\Query\Builder;
+
+abstract class AbstractPaginator
+{
+ /**
+ * The query builder instance.
+ *
+ * @var Builder
+ */
+ protected $query;
+
+ /**
+ * The filter to execute.
+ *
+ * @var string
+ */
+ protected $filter;
+
+ /**
+ * The amount of objects to fetch per page.
+ *
+ * @var int
+ */
+ protected $perPage;
+
+ /**
+ * Whether the operation is critical.
+ *
+ * @var bool
+ */
+ protected $isCritical;
+
+ /**
+ * Constructor.
+ *
+ * @param Builder $query
+ */
+ public function __construct(Builder $query, $filter, $perPage, $isCritical)
+ {
+ $this->query = $query;
+ $this->filter = $filter;
+ $this->perPage = $perPage;
+ $this->isCritical = $isCritical;
+ }
+
+ /**
+ * Execute the pagination request.
+ *
+ * @param LdapInterface $ldap
+ *
+ * @return array
+ */
+ public function execute(LdapInterface $ldap)
+ {
+ $pages = [];
+
+ $this->prepareServerControls();
+
+ do {
+ $this->applyServerControls($ldap);
+
+ if (! $resource = $this->query->run($this->filter)) {
+ break;
+ }
+
+ $this->updateServerControls($ldap, $resource);
+
+ $pages[] = $this->query->parse($resource);
+ } while (! empty($this->fetchCookie()));
+
+ $this->resetServerControls($ldap);
+
+ return $pages;
+ }
+
+ /**
+ * Fetch the pagination cookie.
+ *
+ * @return string
+ */
+ abstract protected function fetchCookie();
+
+ /**
+ * Prepare the server controls before executing the pagination request.
+ *
+ * @return void
+ */
+ abstract protected function prepareServerControls();
+
+ /**
+ * Apply the server controls.
+ *
+ * @param LdapInterface $ldap
+ *
+ * @return void
+ */
+ abstract protected function applyServerControls(LdapInterface $ldap);
+
+ /**
+ * Reset the server controls.
+ *
+ * @param LdapInterface $ldap
+ *
+ * @return mixed
+ */
+ abstract protected function resetServerControls(LdapInterface $ldap);
+
+ /**
+ * Update the server controls.
+ *
+ * @param LdapInterface $ldap
+ * @param resource $resource
+ *
+ * @return void
+ */
+ abstract protected function updateServerControls(LdapInterface $ldap, $resource);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/DeprecatedPaginator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/DeprecatedPaginator.php
new file mode 100644
index 0000000..b4a7f8d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/DeprecatedPaginator.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace LdapRecord\Query\Pagination;
+
+use LdapRecord\LdapInterface;
+
+/**
+ * @deprecated since v2.5.0
+ */
+class DeprecatedPaginator extends AbstractPaginator
+{
+ /**
+ * The pagination cookie.
+ *
+ * @var string
+ */
+ protected $cookie = '';
+
+ /**
+ * @inheritdoc
+ */
+ protected function fetchCookie()
+ {
+ return $this->cookie;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function prepareServerControls()
+ {
+ $this->cookie = '';
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function applyServerControls(LdapInterface $ldap)
+ {
+ $ldap->controlPagedResult($this->perPage, $this->isCritical, $this->cookie);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function updateServerControls(LdapInterface $ldap, $resource)
+ {
+ $ldap->controlPagedResultResponse($resource, $this->cookie);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function resetServerControls(LdapInterface $ldap)
+ {
+ $ldap->controlPagedResult();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/LazyPaginator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/LazyPaginator.php
new file mode 100644
index 0000000..2974b8f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/LazyPaginator.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace LdapRecord\Query\Pagination;
+
+use LdapRecord\LdapInterface;
+
+class LazyPaginator extends Paginator
+{
+ /**
+ * Execute the pagination request.
+ *
+ * @param LdapInterface $ldap
+ *
+ * @return Generator
+ */
+ public function execute(LdapInterface $ldap)
+ {
+ $this->prepareServerControls();
+
+ do {
+ $this->applyServerControls($ldap);
+
+ if (! $resource = $this->query->run($this->filter)) {
+ break;
+ }
+
+ $this->updateServerControls($ldap, $resource);
+
+ yield $this->query->parse($resource);
+ } while (! empty($this->fetchCookie()));
+
+ $this->resetServerControls($ldap);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/Paginator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/Paginator.php
new file mode 100644
index 0000000..9ab6e67
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/Paginator.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace LdapRecord\Query\Pagination;
+
+use LdapRecord\LdapInterface;
+
+class Paginator extends AbstractPaginator
+{
+ /**
+ * @inheritdoc
+ */
+ protected function fetchCookie()
+ {
+ return $this->query->controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie'] ?? null;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function prepareServerControls()
+ {
+ $this->query->addControl(LDAP_CONTROL_PAGEDRESULTS, $this->isCritical, [
+ 'size' => $this->perPage, 'cookie' => '',
+ ]);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function applyServerControls(LdapInterface $ldap)
+ {
+ $ldap->setOption(LDAP_OPT_SERVER_CONTROLS, $this->query->controls);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function updateServerControls(LdapInterface $ldap, $resource)
+ {
+ $errorCode = $dn = $errorMessage = $refs = null;
+
+ $ldap->parseResult(
+ $resource,
+ $errorCode,
+ $dn,
+ $errorMessage,
+ $refs,
+ $this->query->controls
+ );
+
+ $this->resetPageSize();
+ }
+
+ /**
+ * Reset the page control page size.
+ *
+ * @return void
+ */
+ protected function resetPageSize()
+ {
+ $this->query->controls[LDAP_CONTROL_PAGEDRESULTS]['value']['size'] = $this->perPage;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function resetServerControls(LdapInterface $ldap)
+ {
+ $this->query->controls = [];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Support/Arr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Support/Arr.php
new file mode 100644
index 0000000..8fa87a2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Support/Arr.php
@@ -0,0 +1,139 @@
+<?php
+
+namespace LdapRecord\Support;
+
+use ArrayAccess;
+
+class Arr
+{
+ /**
+ * Determine whether the given value is array accessible.
+ *
+ * @param mixed $value
+ *
+ * @return bool
+ */
+ public static function accessible($value)
+ {
+ return is_array($value) || $value instanceof ArrayAccess;
+ }
+
+ /**
+ * Determine if the given key exists in the provided array.
+ *
+ * @param \ArrayAccess|array $array
+ * @param string|int $key
+ *
+ * @return bool
+ */
+ public static function exists($array, $key)
+ {
+ if ($array instanceof ArrayAccess) {
+ return $array->offsetExists($key);
+ }
+
+ return array_key_exists($key, $array);
+ }
+
+ /**
+ * If the given value is not an array and not null, wrap it in one.
+ *
+ * @param mixed $value
+ *
+ * @return array
+ */
+ public static function wrap($value)
+ {
+ if (is_null($value)) {
+ return [];
+ }
+
+ return is_array($value) ? $value : [$value];
+ }
+
+ /**
+ * Return the first element in an array passing a given truth test.
+ *
+ * @param iterable $array
+ * @param callable|null $callback
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public static function first($array, callable $callback = null, $default = null)
+ {
+ if (is_null($callback)) {
+ if (empty($array)) {
+ return Helpers::value($default);
+ }
+
+ foreach ($array as $item) {
+ return $item;
+ }
+ }
+
+ foreach ($array as $key => $value) {
+ if ($callback($value, $key)) {
+ return $value;
+ }
+ }
+
+ return Helpers::value($default);
+ }
+
+ /**
+ * Return the last element in an array passing a given truth test.
+ *
+ * @param array $array
+ * @param callable|null $callback
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public static function last($array, callable $callback = null, $default = null)
+ {
+ if (is_null($callback)) {
+ return empty($array) ? Helpers::value($default) : end($array);
+ }
+
+ return static::first(array_reverse($array, true), $callback, $default);
+ }
+
+ /**
+ * Get an item from an array using "dot" notation.
+ *
+ * @param ArrayAccess|array $array
+ * @param string|int|null $key
+ * @param mixed $default
+ *
+ * @return mixed
+ */
+ public static function get($array, $key, $default = null)
+ {
+ if (! static::accessible($array)) {
+ return Helpers::value($default);
+ }
+
+ if (is_null($key)) {
+ return $array;
+ }
+
+ if (static::exists($array, $key)) {
+ return $array[$key];
+ }
+
+ if (strpos($key, '.') === false) {
+ return $array[$key] ?? Helpers::value($default);
+ }
+
+ foreach (explode('.', $key) as $segment) {
+ if (static::accessible($array) && static::exists($array, $segment)) {
+ $array = $array[$segment];
+ } else {
+ return Helpers::value($default);
+ }
+ }
+
+ return $array;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Support/Helpers.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Support/Helpers.php
new file mode 100644
index 0000000..a55d1d2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Support/Helpers.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace LdapRecord\Support;
+
+use Closure;
+
+class Helpers
+{
+ /**
+ * Return the default value of the given value.
+ *
+ * @param mixed $value
+ *
+ * @return mixed
+ */
+ public static function value($value)
+ {
+ return $value instanceof Closure ? $value() : $value;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/AuthGuardFake.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/AuthGuardFake.php
new file mode 100644
index 0000000..4a69150
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/AuthGuardFake.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace LdapRecord\Testing;
+
+use LdapRecord\Auth\Guard;
+
+class AuthGuardFake extends Guard
+{
+ /**
+ * Always allow binding as configured user.
+ *
+ * @return bool
+ */
+ public function bindAsConfiguredUser()
+ {
+ return true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/ConnectionFake.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/ConnectionFake.php
new file mode 100644
index 0000000..0aa12a1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/ConnectionFake.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace LdapRecord\Testing;
+
+use LdapRecord\Auth\Guard;
+use LdapRecord\Connection;
+use LdapRecord\Models\Model;
+
+class ConnectionFake extends Connection
+{
+ /**
+ * The underlying fake LDAP connection.
+ *
+ * @var LdapFake
+ */
+ protected $ldap;
+
+ /**
+ * Whether the fake is connected.
+ *
+ * @var bool
+ */
+ protected $connected = false;
+
+ /**
+ * Make a new fake LDAP connection instance.
+ *
+ * @param array $config
+ * @param string $ldap
+ *
+ * @return static
+ */
+ public static function make(array $config = [], $ldap = LdapFake::class)
+ {
+ $connection = new static($config, new $ldap());
+
+ $connection->configure();
+
+ return $connection;
+ }
+
+ /**
+ * Set the user to authenticate as.
+ *
+ * @param Model|string $user
+ *
+ * @return $this
+ */
+ public function actingAs($user)
+ {
+ $this->ldap->shouldAuthenticateWith(
+ $user instanceof Model ? $user->getDn() : $user
+ );
+
+ return $this;
+ }
+
+ /**
+ * Set the connection to bypass bind attempts as the configured user.
+ *
+ * @return $this
+ */
+ public function shouldBeConnected()
+ {
+ $this->connected = true;
+
+ $this->authGuardResolver = function () {
+ return new AuthGuardFake($this->ldap, $this->configuration);
+ };
+
+ return $this;
+ }
+
+ /**
+ * Set the connection to attempt binding as the configured user.
+ *
+ * @return $this
+ */
+ public function shouldNotBeConnected()
+ {
+ $this->connected = false;
+
+ $this->authGuardResolver = function () {
+ return new Guard($this->ldap, $this->configuration);
+ };
+
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function isConnected()
+ {
+ return $this->connected ?: parent::isConnected();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/DirectoryFake.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/DirectoryFake.php
new file mode 100644
index 0000000..70640af
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/DirectoryFake.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace LdapRecord\Testing;
+
+use LdapRecord\Container;
+
+class DirectoryFake
+{
+ /**
+ * Setup the fake connection.
+ *
+ * @param string|null $name
+ *
+ * @throws \LdapRecord\ContainerException
+ *
+ * @return ConnectionFake
+ */
+ public static function setup($name = null)
+ {
+ $connection = Container::getConnection($name);
+
+ $fake = static::makeConnectionFake(
+ $connection->getConfiguration()->all()
+ );
+
+ // Replace the connection with a fake.
+ Container::addConnection($fake, $name);
+
+ return $fake;
+ }
+
+ /**
+ * Reset the container.
+ *
+ * @return void
+ */
+ public static function tearDown()
+ {
+ Container::reset();
+ }
+
+ /**
+ * Make a connection fake.
+ *
+ * @param array $config
+ *
+ * @return ConnectionFake
+ */
+ public static function makeConnectionFake(array $config = [])
+ {
+ return ConnectionFake::make($config)->shouldBeConnected();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapExpectation.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapExpectation.php
new file mode 100644
index 0000000..90a5fa2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapExpectation.php
@@ -0,0 +1,303 @@
+<?php
+
+namespace LdapRecord\Testing;
+
+use LdapRecord\LdapRecordException;
+use PHPUnit\Framework\Constraint\Constraint;
+use PHPUnit\Framework\Constraint\IsEqual;
+use UnexpectedValueException;
+
+class LdapExpectation
+{
+ /**
+ * The value to return from the expectation.
+ *
+ * @var mixed
+ */
+ protected $value;
+
+ /**
+ * The exception to throw from the expectation.
+ *
+ * @var null|LdapRecordException|\Exception
+ */
+ protected $exception;
+
+ /**
+ * The amount of times the expectation should be called.
+ *
+ * @var int
+ */
+ protected $count = 1;
+
+ /**
+ * The method that the expectation belongs to.
+ *
+ * @var string
+ */
+ protected $method;
+
+ /**
+ * The methods argument's.
+ *
+ * @var array
+ */
+ protected $args = [];
+
+ /**
+ * Whether the same expectation should be returned indefinitely.
+ *
+ * @var bool
+ */
+ protected $indefinitely = true;
+
+ /**
+ * Whether the expectation should return errors.
+ *
+ * @var bool
+ */
+ protected $errors = false;
+
+ /**
+ * The error number to return.
+ *
+ * @var int
+ */
+ protected $errorCode = 1;
+
+ /**
+ * The last error string to return.
+ *
+ * @var string
+ */
+ protected $errorMessage = '';
+
+ /**
+ * The diagnostic message string to return.
+ *
+ * @var string
+ */
+ protected $errorDiagnosticMessage = '';
+
+ /**
+ * Constructor.
+ *
+ * @param string $method
+ */
+ public function __construct($method)
+ {
+ $this->method = $method;
+ }
+
+ /**
+ * Set the arguments that the operation should receive.
+ *
+ * @param mixed $args
+ *
+ * @return $this
+ */
+ public function with($args)
+ {
+ $args = is_array($args) ? $args : func_get_args();
+
+ foreach ($args as $key => $arg) {
+ if (! $arg instanceof Constraint) {
+ $args[$key] = new IsEqual($arg);
+ }
+ }
+
+ $this->args = $args;
+
+ return $this;
+ }
+
+ /**
+ * Set the expected value to return.
+ *
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function andReturn($value)
+ {
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * The error message to return from the expectation.
+ *
+ * @param int $code
+ * @param string $error
+ * @param string $diagnosticMessage
+ *
+ * @return $this
+ */
+ public function andReturnError($code = 1, $error = '', $diagnosticMessage = '')
+ {
+ $this->errors = true;
+
+ $this->errorCode = $code;
+ $this->errorMessage = $error;
+ $this->errorDiagnosticMessage = $diagnosticMessage;
+
+ return $this;
+ }
+
+ /**
+ * Set the expected exception to throw.
+ *
+ * @param string|\Exception|LdapRecordException $exception
+ *
+ * @return $this
+ */
+ public function andThrow($exception)
+ {
+ if (is_string($exception)) {
+ $exception = new LdapRecordException($exception);
+ }
+
+ $this->exception = $exception;
+
+ return $this;
+ }
+
+ /**
+ * Set the expectation to be only called once.
+ *
+ * @return $this
+ */
+ public function once()
+ {
+ return $this->times(1);
+ }
+
+ /**
+ * Set the expectation to be only called twice.
+ *
+ * @return $this
+ */
+ public function twice()
+ {
+ return $this->times(2);
+ }
+
+ /**
+ * Set the expectation to be called the given number of times.
+ *
+ * @param int $count
+ *
+ * @return $this
+ */
+ public function times($count = 1)
+ {
+ $this->indefinitely = false;
+
+ $this->count = $count;
+
+ return $this;
+ }
+
+ /**
+ * Get the method the expectation belongs to.
+ *
+ * @return string
+ */
+ public function getMethod()
+ {
+ if (is_null($this->method)) {
+ throw new UnexpectedValueException('An expectation must have a method.');
+ }
+
+ return $this->method;
+ }
+
+ /**
+ * Get the expected call count.
+ *
+ * @return int
+ */
+ public function getExpectedCount()
+ {
+ return $this->count;
+ }
+
+ /**
+ * Get the expected arguments.
+ *
+ * @return Constraint[]
+ */
+ public function getExpectedArgs()
+ {
+ return $this->args;
+ }
+
+ /**
+ * Get the expected exception.
+ *
+ * @return null|\Exception|LdapRecordException
+ */
+ public function getExpectedException()
+ {
+ return $this->exception;
+ }
+
+ /**
+ * Get the expected value.
+ *
+ * @return mixed
+ */
+ public function getExpectedValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Determine whether the expectation is returning an error.
+ *
+ * @return bool
+ */
+ public function isReturningError()
+ {
+ return $this->errors;
+ }
+
+ /**
+ * @return int
+ */
+ public function getExpectedErrorCode()
+ {
+ return $this->errorCode;
+ }
+
+ /**
+ * @return string
+ */
+ public function getExpectedErrorMessage()
+ {
+ return $this->errorMessage;
+ }
+
+ /**
+ * @return string
+ */
+ public function getExpectedErrorDiagnosticMessage()
+ {
+ return $this->errorDiagnosticMessage;
+ }
+
+ /**
+ * Decrement the call count of the expectation.
+ *
+ * @return $this
+ */
+ public function decrementCallCount()
+ {
+ if (! $this->indefinitely) {
+ $this->count -= 1;
+ }
+
+ return $this;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapFake.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapFake.php
new file mode 100644
index 0000000..7ba0e15
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapFake.php
@@ -0,0 +1,525 @@
+<?php
+
+namespace LdapRecord\Testing;
+
+use Exception;
+use LdapRecord\DetailedError;
+use LdapRecord\DetectsErrors;
+use LdapRecord\HandlesConnection;
+use LdapRecord\LdapInterface;
+use LdapRecord\Support\Arr;
+use PHPUnit\Framework\Assert as PHPUnit;
+use PHPUnit\Framework\Constraint\Constraint;
+
+class LdapFake implements LdapInterface
+{
+ use HandlesConnection, DetectsErrors;
+
+ /**
+ * The expectations of the LDAP fake.
+ *
+ * @var array
+ */
+ protected $expectations = [];
+
+ /**
+ * The default fake error number.
+ *
+ * @var int
+ */
+ protected $errNo = 1;
+
+ /**
+ * The default fake last error string.
+ *
+ * @var string
+ */
+ protected $lastError = '';
+
+ /**
+ * The default fake diagnostic message string.
+ *
+ * @var string
+ */
+ protected $diagnosticMessage = '';
+
+ /**
+ * Create a new expected operation.
+ *
+ * @param string $method
+ *
+ * @return LdapExpectation
+ */
+ public static function operation($method)
+ {
+ return new LdapExpectation($method);
+ }
+
+ /**
+ * Set the user that will pass binding.
+ *
+ * @param string $dn
+ *
+ * @return $this
+ */
+ public function shouldAuthenticateWith($dn)
+ {
+ return $this->expect(
+ static::operation('bind')->with($dn, PHPUnit::anything())->andReturn(true)
+ );
+ }
+
+ /**
+ * Add an LDAP method expectation.
+ *
+ * @param LdapExpectation|array $expectations
+ *
+ * @return $this
+ */
+ public function expect($expectations = [])
+ {
+ $expectations = Arr::wrap($expectations);
+
+ foreach ($expectations as $key => $expectation) {
+ // If the key is non-numeric, we will assume
+ // that the string is the method name and
+ // the expectation is the return value.
+ if (! is_numeric($key)) {
+ $expectation = static::operation($key)->andReturn($expectation);
+ }
+
+ if (! $expectation instanceof LdapExpectation) {
+ $expectation = static::operation($expectation);
+ }
+
+ $this->expectations[$expectation->getMethod()][] = $expectation;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Determine if the method has any expectations.
+ *
+ * @param string $method
+ *
+ * @return bool
+ */
+ public function hasExpectations($method)
+ {
+ return count($this->getExpectations($method)) > 0;
+ }
+
+ /**
+ * Get expectations by method.
+ *
+ * @param string $method
+ *
+ * @return LdapExpectation[]|mixed
+ */
+ public function getExpectations($method)
+ {
+ return $this->expectations[$method] ?? [];
+ }
+
+ /**
+ * Remove an expectation by method and key.
+ *
+ * @param string $method
+ * @param int $key
+ *
+ * @return void
+ */
+ public function removeExpectation($method, $key)
+ {
+ unset($this->expectations[$method][$key]);
+ }
+
+ /**
+ * Set the error number of a failed bind attempt.
+ *
+ * @param int $number
+ *
+ * @return $this
+ */
+ public function shouldReturnErrorNumber($number = 1)
+ {
+ $this->errNo = $number;
+
+ return $this;
+ }
+
+ /**
+ * Set the last error of a failed bind attempt.
+ *
+ * @param string $message
+ *
+ * @return $this
+ */
+ public function shouldReturnError($message = '')
+ {
+ $this->lastError = $message;
+
+ return $this;
+ }
+
+ /**
+ * Set the diagnostic message of a failed bind attempt.
+ *
+ * @param string $message
+ *
+ * @return $this
+ */
+ public function shouldReturnDiagnosticMessage($message = '')
+ {
+ $this->diagnosticMessage = $message;
+
+ return $this;
+ }
+
+ /**
+ * Return a fake error number.
+ *
+ * @return int
+ */
+ public function errNo()
+ {
+ return $this->errNo;
+ }
+
+ /**
+ * Return a fake error.
+ *
+ * @return string
+ */
+ public function getLastError()
+ {
+ return $this->lastError;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getDiagnosticMessage()
+ {
+ return $this->diagnosticMessage;
+ }
+
+ /**
+ * Return a fake detailed error.
+ *
+ * @return DetailedError
+ */
+ public function getDetailedError()
+ {
+ return new DetailedError(
+ $this->errNo(),
+ $this->getLastError(),
+ $this->getDiagnosticMessage()
+ );
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getEntries($searchResults)
+ {
+ return $searchResults;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function isUsingSSL()
+ {
+ return $this->hasExpectations('isUsingSSL')
+ ? $this->resolveExpectation('isUsingSSL')
+ : $this->useSSL;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function isUsingTLS()
+ {
+ return $this->hasExpectations('isUsingTLS')
+ ? $this->resolveExpectation('isUsingTLS')
+ : $this->useTLS;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function isBound()
+ {
+ return $this->hasExpectations('isBound')
+ ? $this->resolveExpectation('isBound')
+ : $this->bound;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setOption($option, $value)
+ {
+ return $this->hasExpectations('setOption')
+ ? $this->resolveExpectation('setOption', func_get_args())
+ : true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getOption($option, &$value = null)
+ {
+ return $this->resolveExpectation('getOption', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function startTLS()
+ {
+ return $this->resolveExpectation('startTLS', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function connect($hosts = [], $port = 389)
+ {
+ $this->bound = false;
+
+ $this->host = $this->makeConnectionUris($hosts, $port);
+
+ return $this->connection = $this->hasExpectations('connect')
+ ? $this->resolveExpectation('connect', func_get_args())
+ : true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function close()
+ {
+ $this->connection = null;
+ $this->bound = false;
+ $this->host = null;
+
+ return $this->hasExpectations('close')
+ ? $this->resolveExpectation('close')
+ : true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function bind($username, $password)
+ {
+ return $this->bound = $this->resolveExpectation('bind', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function search($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = null, $serverControls = [])
+ {
+ return $this->resolveExpectation('search', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function listing($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = null, $serverControls = [])
+ {
+ return $this->resolveExpectation('listing', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function read($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = null, $serverControls = [])
+ {
+ return $this->resolveExpectation('read', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function parseResult($result, &$errorCode, &$dn, &$errorMessage, &$referrals, &$serverControls = [])
+ {
+ return $this->resolveExpectation('parseResult', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function add($dn, array $entry)
+ {
+ return $this->resolveExpectation('add', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function delete($dn)
+ {
+ return $this->resolveExpectation('delete', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function rename($dn, $newRdn, $newParent, $deleteOldRdn = false)
+ {
+ return $this->resolveExpectation('rename', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function modify($dn, array $entry)
+ {
+ return $this->resolveExpectation('modify', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function modifyBatch($dn, array $values)
+ {
+ return $this->resolveExpectation('modifyBatch', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function modAdd($dn, array $entry)
+ {
+ return $this->resolveExpectation('modAdd', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function modReplace($dn, array $entry)
+ {
+ return $this->resolveExpectation('modReplace', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function modDelete($dn, array $entry)
+ {
+ return $this->resolveExpectation('modDelete', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function controlPagedResult($pageSize = 1000, $isCritical = false, $cookie = '')
+ {
+ return $this->resolveExpectation('controlPagedResult', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function controlPagedResultResponse($result, &$cookie)
+ {
+ return $this->resolveExpectation('controlPagedResultResponse', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function freeResult($result)
+ {
+ return $this->resolveExpectation('freeResult', func_get_args());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function err2Str($number)
+ {
+ return $this->resolveExpectation('err2Str', func_get_args());
+ }
+
+ /**
+ * Resolve the methods expectations.
+ *
+ * @param string $method
+ * @param array $args
+ *
+ * @throws Exception
+ *
+ * @return mixed
+ */
+ protected function resolveExpectation($method, array $args = [])
+ {
+ foreach ($this->getExpectations($method) as $key => $expectation) {
+ $this->assertMethodArgumentsMatch($method, $expectation->getExpectedArgs(), $args);
+
+ $expectation->decrementCallCount();
+
+ if ($expectation->getExpectedCount() === 0) {
+ $this->removeExpectation($method, $key);
+ }
+
+ if (! is_null($exception = $expectation->getExpectedException())) {
+ throw $exception;
+ }
+
+ if ($expectation->isReturningError()) {
+ $this->applyExpectationError($expectation);
+ }
+
+ return $expectation->getExpectedValue();
+ }
+
+ throw new Exception("LDAP method [$method] was unexpected.");
+ }
+
+ /**
+ * Apply the expectation error to the fake.
+ *
+ * @param LdapExpectation $expectation
+ *
+ * @return void
+ */
+ protected function applyExpectationError(LdapExpectation $expectation)
+ {
+ $this->shouldReturnError($expectation->getExpectedErrorMessage());
+ $this->shouldReturnErrorNumber($expectation->getExpectedErrorCode());
+ $this->shouldReturnDiagnosticMessage($expectation->getExpectedErrorDiagnosticMessage());
+ }
+
+ /**
+ * Assert that the expected arguments match the operations arguments.
+ *
+ * @param string $method
+ * @param Constraint[] $expectedArgs
+ * @param array $methodArgs
+ *
+ * @return void
+ */
+ protected function assertMethodArgumentsMatch($method, array $expectedArgs = [], array $methodArgs = [])
+ {
+ foreach ($expectedArgs as $key => $constraint) {
+ $argNumber = $key + 1;
+
+ PHPUnit::assertArrayHasKey(
+ $key,
+ $methodArgs,
+ "LDAP method [$method] argument #{$argNumber} does not exist."
+ );
+
+ $constraint->evaluate(
+ $methodArgs[$key],
+ "LDAP method [$method] expectation failed."
+ );
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Utilities.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Utilities.php
new file mode 100644
index 0000000..0f0ca3c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Utilities.php
@@ -0,0 +1,196 @@
+<?php
+
+namespace LdapRecord;
+
+class Utilities
+{
+ /**
+ * Converts a DN string into an array of RDNs.
+ *
+ * This will also decode hex characters into their true
+ * UTF-8 representation embedded inside the DN as well.
+ *
+ * @param string $dn
+ * @param bool $removeAttributePrefixes
+ *
+ * @return array|false
+ */
+ public static function explodeDn($dn, $removeAttributePrefixes = true)
+ {
+ $dn = ldap_explode_dn($dn, ($removeAttributePrefixes ? 1 : 0));
+
+ if (! is_array($dn)) {
+ return false;
+ }
+
+ if (! array_key_exists('count', $dn)) {
+ return false;
+ }
+
+ unset($dn['count']);
+
+ foreach ($dn as $rdn => $value) {
+ $dn[$rdn] = static::unescape($value);
+ }
+
+ return $dn;
+ }
+
+ /**
+ * Un-escapes a hexadecimal string into its original string representation.
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ public static function unescape($value)
+ {
+ return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function ($matches) {
+ return chr(hexdec($matches[1]));
+ }, $value);
+ }
+
+ /**
+ * Convert a binary SID to a string SID.
+ *
+ * @author Chad Sikorra
+ *
+ * @see https://github.com/ChadSikorra
+ * @see https://stackoverflow.com/questions/39533560/php-ldap-get-user-sid
+ *
+ * @param string $value The Binary SID
+ *
+ * @return string|null
+ */
+ public static function binarySidToString($value)
+ {
+ // Revision - 8bit unsigned int (C1)
+ // Count - 8bit unsigned int (C1)
+ // 2 null bytes
+ // ID - 32bit unsigned long, big-endian order
+ $sid = @unpack('C1rev/C1count/x2/N1id', $value);
+
+ if (! isset($sid['id']) || ! isset($sid['rev'])) {
+ return;
+ }
+
+ $revisionLevel = $sid['rev'];
+
+ $identifierAuthority = $sid['id'];
+
+ $subs = isset($sid['count']) ? $sid['count'] : 0;
+
+ $sidHex = $subs ? bin2hex($value) : '';
+
+ $subAuthorities = [];
+
+ // The sub-authorities depend on the count, so only get as
+ // many as the count, regardless of data beyond it.
+ for ($i = 0; $i < $subs; $i++) {
+ $data = implode(array_reverse(
+ str_split(
+ substr($sidHex, 16 + ($i * 8), 8),
+ 2
+ )
+ ));
+
+ $subAuthorities[] = hexdec($data);
+ }
+
+ // Tack on the 'S-' and glue it all together...
+ return 'S-'.$revisionLevel.'-'.$identifierAuthority.implode(
+ preg_filter('/^/', '-', $subAuthorities)
+ );
+ }
+
+ /**
+ * Convert a binary GUID to a string GUID.
+ *
+ * @param string $binGuid
+ *
+ * @return string|null
+ */
+ public static function binaryGuidToString($binGuid)
+ {
+ if (trim($binGuid) == '' || is_null($binGuid)) {
+ return;
+ }
+
+ $hex = unpack('H*hex', $binGuid)['hex'];
+
+ $hex1 = substr($hex, -26, 2).substr($hex, -28, 2).substr($hex, -30, 2).substr($hex, -32, 2);
+ $hex2 = substr($hex, -22, 2).substr($hex, -24, 2);
+ $hex3 = substr($hex, -18, 2).substr($hex, -20, 2);
+ $hex4 = substr($hex, -16, 4);
+ $hex5 = substr($hex, -12, 12);
+
+ return sprintf('%s-%s-%s-%s-%s', $hex1, $hex2, $hex3, $hex4, $hex5);
+ }
+
+ /**
+ * Converts a string GUID to it's hex variant.
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ public static function stringGuidToHex($string)
+ {
+ $hex = '\\'.substr($string, 6, 2).'\\'.substr($string, 4, 2).'\\'.substr($string, 2, 2).'\\'.substr($string, 0, 2);
+ $hex = $hex.'\\'.substr($string, 11, 2).'\\'.substr($string, 9, 2);
+ $hex = $hex.'\\'.substr($string, 16, 2).'\\'.substr($string, 14, 2);
+ $hex = $hex.'\\'.substr($string, 19, 2).'\\'.substr($string, 21, 2);
+ $hex = $hex.'\\'.substr($string, 24, 2).'\\'.substr($string, 26, 2).'\\'.substr($string, 28, 2).'\\'.substr($string, 30, 2).'\\'.substr($string, 32, 2).'\\'.substr($string, 34, 2);
+
+ return $hex;
+ }
+
+ /**
+ * Round a Windows timestamp down to seconds and remove
+ * the seconds between 1601-01-01 and 1970-01-01.
+ *
+ * @param float $windowsTime
+ *
+ * @return float
+ */
+ public static function convertWindowsTimeToUnixTime($windowsTime)
+ {
+ return round($windowsTime / 10000000) - 11644473600;
+ }
+
+ /**
+ * Convert a Unix timestamp to Windows timestamp.
+ *
+ * @param float $unixTime
+ *
+ * @return float
+ */
+ public static function convertUnixTimeToWindowsTime($unixTime)
+ {
+ return ($unixTime + 11644473600) * 10000000;
+ }
+
+ /**
+ * Validates that the inserted string is an object SID.
+ *
+ * @param string $sid
+ *
+ * @return bool
+ */
+ public static function isValidSid($sid)
+ {
+ return (bool) preg_match("/^S-\d(-\d{1,10}){1,16}$/i", $sid);
+ }
+
+ /**
+ * Validates that the inserted string is an object GUID.
+ *
+ * @param string $guid
+ *
+ * @return bool
+ */
+ public static function isValidGuid($guid)
+ {
+ return (bool) preg_match('/^([0-9a-fA-F]){8}(-([0-9a-fA-F]){4}){3}-([0-9a-fA-F]){12}$/', $guid);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Access/Authorizable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Access/Authorizable.php
new file mode 100644
index 0000000..cedeb6e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Access/Authorizable.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Illuminate\Contracts\Auth\Access;
+
+interface Authorizable
+{
+ /**
+ * Determine if the entity has a given ability.
+ *
+ * @param iterable|string $abilities
+ * @param array|mixed $arguments
+ * @return bool
+ */
+ public function can($abilities, $arguments = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Access/Gate.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Access/Gate.php
new file mode 100644
index 0000000..b88ab17
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Access/Gate.php
@@ -0,0 +1,150 @@
+<?php
+
+namespace Illuminate\Contracts\Auth\Access;
+
+interface Gate
+{
+ /**
+ * Determine if a given ability has been defined.
+ *
+ * @param string $ability
+ * @return bool
+ */
+ public function has($ability);
+
+ /**
+ * Define a new ability.
+ *
+ * @param string $ability
+ * @param callable|string $callback
+ * @return $this
+ */
+ public function define($ability, $callback);
+
+ /**
+ * Define abilities for a resource.
+ *
+ * @param string $name
+ * @param string $class
+ * @param array|null $abilities
+ * @return $this
+ */
+ public function resource($name, $class, array $abilities = null);
+
+ /**
+ * Define a policy class for a given class type.
+ *
+ * @param string $class
+ * @param string $policy
+ * @return $this
+ */
+ public function policy($class, $policy);
+
+ /**
+ * Register a callback to run before all Gate checks.
+ *
+ * @param callable $callback
+ * @return $this
+ */
+ public function before(callable $callback);
+
+ /**
+ * Register a callback to run after all Gate checks.
+ *
+ * @param callable $callback
+ * @return $this
+ */
+ public function after(callable $callback);
+
+ /**
+ * Determine if the given ability should be granted for the current user.
+ *
+ * @param string $ability
+ * @param array|mixed $arguments
+ * @return bool
+ */
+ public function allows($ability, $arguments = []);
+
+ /**
+ * Determine if the given ability should be denied for the current user.
+ *
+ * @param string $ability
+ * @param array|mixed $arguments
+ * @return bool
+ */
+ public function denies($ability, $arguments = []);
+
+ /**
+ * Determine if all of the given abilities should be granted for the current user.
+ *
+ * @param iterable|string $abilities
+ * @param array|mixed $arguments
+ * @return bool
+ */
+ public function check($abilities, $arguments = []);
+
+ /**
+ * Determine if any one of the given abilities should be granted for the current user.
+ *
+ * @param iterable|string $abilities
+ * @param array|mixed $arguments
+ * @return bool
+ */
+ public function any($abilities, $arguments = []);
+
+ /**
+ * Determine if the given ability should be granted for the current user.
+ *
+ * @param string $ability
+ * @param array|mixed $arguments
+ * @return \Illuminate\Auth\Access\Response
+ *
+ * @throws \Illuminate\Auth\Access\AuthorizationException
+ */
+ public function authorize($ability, $arguments = []);
+
+ /**
+ * Inspect the user for the given ability.
+ *
+ * @param string $ability
+ * @param array|mixed $arguments
+ * @return \Illuminate\Auth\Access\Response
+ */
+ public function inspect($ability, $arguments = []);
+
+ /**
+ * Get the raw result from the authorization callback.
+ *
+ * @param string $ability
+ * @param array|mixed $arguments
+ * @return mixed
+ *
+ * @throws \Illuminate\Auth\Access\AuthorizationException
+ */
+ public function raw($ability, $arguments = []);
+
+ /**
+ * Get a policy instance for a given class.
+ *
+ * @param object|string $class
+ * @return mixed
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function getPolicyFor($class);
+
+ /**
+ * Get a guard instance for the given user.
+ *
+ * @param \Illuminate\Contracts\Auth\Authenticatable|mixed $user
+ * @return static
+ */
+ public function forUser($user);
+
+ /**
+ * Get all of the defined abilities.
+ *
+ * @return array
+ */
+ public function abilities();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Authenticatable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Authenticatable.php
new file mode 100644
index 0000000..ac4ed88
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Authenticatable.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Illuminate\Contracts\Auth;
+
+interface Authenticatable
+{
+ /**
+ * Get the name of the unique identifier for the user.
+ *
+ * @return string
+ */
+ public function getAuthIdentifierName();
+
+ /**
+ * Get the unique identifier for the user.
+ *
+ * @return mixed
+ */
+ public function getAuthIdentifier();
+
+ /**
+ * Get the password for the user.
+ *
+ * @return string
+ */
+ public function getAuthPassword();
+
+ /**
+ * Get the token value for the "remember me" session.
+ *
+ * @return string
+ */
+ public function getRememberToken();
+
+ /**
+ * Set the token value for the "remember me" session.
+ *
+ * @param string $value
+ * @return void
+ */
+ public function setRememberToken($value);
+
+ /**
+ * Get the column name for the "remember me" token.
+ *
+ * @return string
+ */
+ public function getRememberTokenName();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/CanResetPassword.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/CanResetPassword.php
new file mode 100644
index 0000000..3a67707
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/CanResetPassword.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Illuminate\Contracts\Auth;
+
+interface CanResetPassword
+{
+ /**
+ * Get the e-mail address where password reset links are sent.
+ *
+ * @return string
+ */
+ public function getEmailForPasswordReset();
+
+ /**
+ * Send the password reset notification.
+ *
+ * @param string $token
+ * @return void
+ */
+ public function sendPasswordResetNotification($token);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Factory.php
new file mode 100644
index 0000000..d76ee76
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Factory.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Illuminate\Contracts\Auth;
+
+interface Factory
+{
+ /**
+ * Get a guard instance by name.
+ *
+ * @param string|null $name
+ * @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
+ */
+ public function guard($name = null);
+
+ /**
+ * Set the default guard the factory should serve.
+ *
+ * @param string $name
+ * @return void
+ */
+ public function shouldUse($name);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Guard.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Guard.php
new file mode 100644
index 0000000..2a27fb5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Guard.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Illuminate\Contracts\Auth;
+
+interface Guard
+{
+ /**
+ * Determine if the current user is authenticated.
+ *
+ * @return bool
+ */
+ public function check();
+
+ /**
+ * Determine if the current user is a guest.
+ *
+ * @return bool
+ */
+ public function guest();
+
+ /**
+ * Get the currently authenticated user.
+ *
+ * @return \Illuminate\Contracts\Auth\Authenticatable|null
+ */
+ public function user();
+
+ /**
+ * Get the ID for the currently authenticated user.
+ *
+ * @return int|string|null
+ */
+ public function id();
+
+ /**
+ * Validate a user's credentials.
+ *
+ * @param array $credentials
+ * @return bool
+ */
+ public function validate(array $credentials = []);
+
+ /**
+ * Set the current user.
+ *
+ * @param \Illuminate\Contracts\Auth\Authenticatable $user
+ * @return void
+ */
+ public function setUser(Authenticatable $user);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Middleware/AuthenticatesRequests.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Middleware/AuthenticatesRequests.php
new file mode 100644
index 0000000..b782761
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/Middleware/AuthenticatesRequests.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Illuminate\Contracts\Auth\Middleware;
+
+interface AuthenticatesRequests
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/MustVerifyEmail.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/MustVerifyEmail.php
new file mode 100644
index 0000000..5b8b105
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/MustVerifyEmail.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Illuminate\Contracts\Auth;
+
+interface MustVerifyEmail
+{
+ /**
+ * Determine if the user has verified their email address.
+ *
+ * @return bool
+ */
+ public function hasVerifiedEmail();
+
+ /**
+ * Mark the given user's email as verified.
+ *
+ * @return bool
+ */
+ public function markEmailAsVerified();
+
+ /**
+ * Send the email verification notification.
+ *
+ * @return void
+ */
+ public function sendEmailVerificationNotification();
+
+ /**
+ * Get the email address that should be used for verification.
+ *
+ * @return string
+ */
+ public function getEmailForVerification();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/PasswordBroker.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/PasswordBroker.php
new file mode 100644
index 0000000..bbbe9b5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/PasswordBroker.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Illuminate\Contracts\Auth;
+
+use Closure;
+
+interface PasswordBroker
+{
+ /**
+ * Constant representing a successfully sent reminder.
+ *
+ * @var string
+ */
+ const RESET_LINK_SENT = 'passwords.sent';
+
+ /**
+ * Constant representing a successfully reset password.
+ *
+ * @var string
+ */
+ const PASSWORD_RESET = 'passwords.reset';
+
+ /**
+ * Constant representing the user not found response.
+ *
+ * @var string
+ */
+ const INVALID_USER = 'passwords.user';
+
+ /**
+ * Constant representing an invalid token.
+ *
+ * @var string
+ */
+ const INVALID_TOKEN = 'passwords.token';
+
+ /**
+ * Constant representing a throttled reset attempt.
+ *
+ * @var string
+ */
+ const RESET_THROTTLED = 'passwords.throttled';
+
+ /**
+ * Send a password reset link to a user.
+ *
+ * @param array $credentials
+ * @param \Closure|null $callback
+ * @return string
+ */
+ public function sendResetLink(array $credentials, Closure $callback = null);
+
+ /**
+ * Reset the password for the given token.
+ *
+ * @param array $credentials
+ * @param \Closure $callback
+ * @return mixed
+ */
+ public function reset(array $credentials, Closure $callback);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/PasswordBrokerFactory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/PasswordBrokerFactory.php
new file mode 100644
index 0000000..47b1c08
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/PasswordBrokerFactory.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Auth;
+
+interface PasswordBrokerFactory
+{
+ /**
+ * Get a password broker instance by name.
+ *
+ * @param string|null $name
+ * @return mixed
+ */
+ public function broker($name = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/StatefulGuard.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/StatefulGuard.php
new file mode 100644
index 0000000..faf1497
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/StatefulGuard.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Illuminate\Contracts\Auth;
+
+interface StatefulGuard extends Guard
+{
+ /**
+ * Attempt to authenticate a user using the given credentials.
+ *
+ * @param array $credentials
+ * @param bool $remember
+ * @return bool
+ */
+ public function attempt(array $credentials = [], $remember = false);
+
+ /**
+ * Log a user into the application without sessions or cookies.
+ *
+ * @param array $credentials
+ * @return bool
+ */
+ public function once(array $credentials = []);
+
+ /**
+ * Log a user into the application.
+ *
+ * @param \Illuminate\Contracts\Auth\Authenticatable $user
+ * @param bool $remember
+ * @return void
+ */
+ public function login(Authenticatable $user, $remember = false);
+
+ /**
+ * Log the given user ID into the application.
+ *
+ * @param mixed $id
+ * @param bool $remember
+ * @return \Illuminate\Contracts\Auth\Authenticatable|bool
+ */
+ public function loginUsingId($id, $remember = false);
+
+ /**
+ * Log the given user ID into the application without sessions or cookies.
+ *
+ * @param mixed $id
+ * @return \Illuminate\Contracts\Auth\Authenticatable|bool
+ */
+ public function onceUsingId($id);
+
+ /**
+ * Determine if the user was authenticated via "remember me" cookie.
+ *
+ * @return bool
+ */
+ public function viaRemember();
+
+ /**
+ * Log the user out of the application.
+ *
+ * @return void
+ */
+ public function logout();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/SupportsBasicAuth.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/SupportsBasicAuth.php
new file mode 100644
index 0000000..9c54591
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/SupportsBasicAuth.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Illuminate\Contracts\Auth;
+
+interface SupportsBasicAuth
+{
+ /**
+ * Attempt to authenticate using HTTP Basic Auth.
+ *
+ * @param string $field
+ * @param array $extraConditions
+ * @return \Symfony\Component\HttpFoundation\Response|null
+ */
+ public function basic($field = 'email', $extraConditions = []);
+
+ /**
+ * Perform a stateless HTTP Basic login attempt.
+ *
+ * @param string $field
+ * @param array $extraConditions
+ * @return \Symfony\Component\HttpFoundation\Response|null
+ */
+ public function onceBasic($field = 'email', $extraConditions = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/UserProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/UserProvider.php
new file mode 100644
index 0000000..a2ab122
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Auth/UserProvider.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Illuminate\Contracts\Auth;
+
+interface UserProvider
+{
+ /**
+ * Retrieve a user by their unique identifier.
+ *
+ * @param mixed $identifier
+ * @return \Illuminate\Contracts\Auth\Authenticatable|null
+ */
+ public function retrieveById($identifier);
+
+ /**
+ * Retrieve a user by their unique identifier and "remember me" token.
+ *
+ * @param mixed $identifier
+ * @param string $token
+ * @return \Illuminate\Contracts\Auth\Authenticatable|null
+ */
+ public function retrieveByToken($identifier, $token);
+
+ /**
+ * Update the "remember me" token for the given user in storage.
+ *
+ * @param \Illuminate\Contracts\Auth\Authenticatable $user
+ * @param string $token
+ * @return void
+ */
+ public function updateRememberToken(Authenticatable $user, $token);
+
+ /**
+ * Retrieve a user by the given credentials.
+ *
+ * @param array $credentials
+ * @return \Illuminate\Contracts\Auth\Authenticatable|null
+ */
+ public function retrieveByCredentials(array $credentials);
+
+ /**
+ * Validate a user against the given credentials.
+ *
+ * @param \Illuminate\Contracts\Auth\Authenticatable $user
+ * @param array $credentials
+ * @return bool
+ */
+ public function validateCredentials(Authenticatable $user, array $credentials);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/Broadcaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/Broadcaster.php
new file mode 100644
index 0000000..1034e44
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/Broadcaster.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Illuminate\Contracts\Broadcasting;
+
+interface Broadcaster
+{
+ /**
+ * Authenticate the incoming request for a given channel.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @return mixed
+ */
+ public function auth($request);
+
+ /**
+ * Return the valid authentication response.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @param mixed $result
+ * @return mixed
+ */
+ public function validAuthenticationResponse($request, $result);
+
+ /**
+ * Broadcast the given event.
+ *
+ * @param array $channels
+ * @param string $event
+ * @param array $payload
+ * @return void
+ */
+ public function broadcast(array $channels, $event, array $payload = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/Factory.php
new file mode 100644
index 0000000..1a4f48f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/Factory.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Broadcasting;
+
+interface Factory
+{
+ /**
+ * Get a broadcaster implementation by name.
+ *
+ * @param string|null $name
+ * @return \Illuminate\Contracts\Broadcasting\Broadcaster
+ */
+ public function connection($name = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/HasBroadcastChannel.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/HasBroadcastChannel.php
new file mode 100644
index 0000000..3b2c401
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/HasBroadcastChannel.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Illuminate\Contracts\Broadcasting;
+
+interface HasBroadcastChannel
+{
+ /**
+ * Get the broadcast channel route definition that is associated with the given entity.
+ *
+ * @return string
+ */
+ public function broadcastChannelRoute();
+
+ /**
+ * Get the broadcast channel name that is associated with the given entity.
+ *
+ * @return string
+ */
+ public function broadcastChannel();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/ShouldBroadcast.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/ShouldBroadcast.php
new file mode 100644
index 0000000..a4802fe
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/ShouldBroadcast.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Illuminate\Contracts\Broadcasting;
+
+interface ShouldBroadcast
+{
+ /**
+ * Get the channels the event should broadcast on.
+ *
+ * @return \Illuminate\Broadcasting\Channel|\Illuminate\Broadcasting\Channel[]
+ */
+ public function broadcastOn();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/ShouldBroadcastNow.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/ShouldBroadcastNow.php
new file mode 100644
index 0000000..eba3584
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Broadcasting/ShouldBroadcastNow.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Illuminate\Contracts\Broadcasting;
+
+interface ShouldBroadcastNow extends ShouldBroadcast
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Bus/Dispatcher.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Bus/Dispatcher.php
new file mode 100644
index 0000000..5cbbd92
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Bus/Dispatcher.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace Illuminate\Contracts\Bus;
+
+interface Dispatcher
+{
+ /**
+ * Dispatch a command to its appropriate handler.
+ *
+ * @param mixed $command
+ * @return mixed
+ */
+ public function dispatch($command);
+
+ /**
+ * Dispatch a command to its appropriate handler in the current process.
+ *
+ * Queueable jobs will be dispatched to the "sync" queue.
+ *
+ * @param mixed $command
+ * @param mixed $handler
+ * @return mixed
+ */
+ public function dispatchSync($command, $handler = null);
+
+ /**
+ * Dispatch a command to its appropriate handler in the current process.
+ *
+ * @param mixed $command
+ * @param mixed $handler
+ * @return mixed
+ */
+ public function dispatchNow($command, $handler = null);
+
+ /**
+ * Determine if the given command has a handler.
+ *
+ * @param mixed $command
+ * @return bool
+ */
+ public function hasCommandHandler($command);
+
+ /**
+ * Retrieve the handler for a command.
+ *
+ * @param mixed $command
+ * @return bool|mixed
+ */
+ public function getCommandHandler($command);
+
+ /**
+ * Set the pipes commands should be piped through before dispatching.
+ *
+ * @param array $pipes
+ * @return $this
+ */
+ public function pipeThrough(array $pipes);
+
+ /**
+ * Map a command to a handler.
+ *
+ * @param array $map
+ * @return $this
+ */
+ public function map(array $map);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Bus/QueueingDispatcher.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Bus/QueueingDispatcher.php
new file mode 100644
index 0000000..ff84e27
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Bus/QueueingDispatcher.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Illuminate\Contracts\Bus;
+
+interface QueueingDispatcher extends Dispatcher
+{
+ /**
+ * Attempt to find the batch with the given ID.
+ *
+ * @param string $batchId
+ * @return \Illuminate\Bus\Batch|null
+ */
+ public function findBatch(string $batchId);
+
+ /**
+ * Create a new batch of queueable jobs.
+ *
+ * @param \Illuminate\Support\Collection|array $jobs
+ * @return \Illuminate\Bus\PendingBatch
+ */
+ public function batch($jobs);
+
+ /**
+ * Dispatch a command to its appropriate handler behind a queue.
+ *
+ * @param mixed $command
+ * @return mixed
+ */
+ public function dispatchToQueue($command);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Factory.php
new file mode 100644
index 0000000..3924662
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Factory.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Cache;
+
+interface Factory
+{
+ /**
+ * Get a cache store instance by name.
+ *
+ * @param string|null $name
+ * @return \Illuminate\Contracts\Cache\Repository
+ */
+ public function store($name = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Lock.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Lock.php
new file mode 100644
index 0000000..03f633a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Lock.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Illuminate\Contracts\Cache;
+
+interface Lock
+{
+ /**
+ * Attempt to acquire the lock.
+ *
+ * @param callable|null $callback
+ * @return mixed
+ */
+ public function get($callback = null);
+
+ /**
+ * Attempt to acquire the lock for the given number of seconds.
+ *
+ * @param int $seconds
+ * @param callable|null $callback
+ * @return mixed
+ */
+ public function block($seconds, $callback = null);
+
+ /**
+ * Release the lock.
+ *
+ * @return bool
+ */
+ public function release();
+
+ /**
+ * Returns the current owner of the lock.
+ *
+ * @return string
+ */
+ public function owner();
+
+ /**
+ * Releases this lock in disregard of ownership.
+ *
+ * @return void
+ */
+ public function forceRelease();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/LockProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/LockProvider.php
new file mode 100644
index 0000000..37d4ef6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/LockProvider.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Illuminate\Contracts\Cache;
+
+interface LockProvider
+{
+ /**
+ * Get a lock instance.
+ *
+ * @param string $name
+ * @param int $seconds
+ * @param string|null $owner
+ * @return \Illuminate\Contracts\Cache\Lock
+ */
+ public function lock($name, $seconds = 0, $owner = null);
+
+ /**
+ * Restore a lock instance using the owner identifier.
+ *
+ * @param string $name
+ * @param string $owner
+ * @return \Illuminate\Contracts\Cache\Lock
+ */
+ public function restoreLock($name, $owner);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/LockTimeoutException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/LockTimeoutException.php
new file mode 100644
index 0000000..53327e2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/LockTimeoutException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Illuminate\Contracts\Cache;
+
+use Exception;
+
+class LockTimeoutException extends Exception
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Repository.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Repository.php
new file mode 100644
index 0000000..5b78af5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Repository.php
@@ -0,0 +1,108 @@
+<?php
+
+namespace Illuminate\Contracts\Cache;
+
+use Closure;
+use Psr\SimpleCache\CacheInterface;
+
+interface Repository extends CacheInterface
+{
+ /**
+ * Retrieve an item from the cache and delete it.
+ *
+ * @param string $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public function pull($key, $default = null);
+
+ /**
+ * Store an item in the cache.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param \DateTimeInterface|\DateInterval|int|null $ttl
+ * @return bool
+ */
+ public function put($key, $value, $ttl = null);
+
+ /**
+ * Store an item in the cache if the key does not exist.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param \DateTimeInterface|\DateInterval|int|null $ttl
+ * @return bool
+ */
+ public function add($key, $value, $ttl = null);
+
+ /**
+ * Increment the value of an item in the cache.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return int|bool
+ */
+ public function increment($key, $value = 1);
+
+ /**
+ * Decrement the value of an item in the cache.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return int|bool
+ */
+ public function decrement($key, $value = 1);
+
+ /**
+ * Store an item in the cache indefinitely.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return bool
+ */
+ public function forever($key, $value);
+
+ /**
+ * Get an item from the cache, or execute the given Closure and store the result.
+ *
+ * @param string $key
+ * @param \DateTimeInterface|\DateInterval|int|null $ttl
+ * @param \Closure $callback
+ * @return mixed
+ */
+ public function remember($key, $ttl, Closure $callback);
+
+ /**
+ * Get an item from the cache, or execute the given Closure and store the result forever.
+ *
+ * @param string $key
+ * @param \Closure $callback
+ * @return mixed
+ */
+ public function sear($key, Closure $callback);
+
+ /**
+ * Get an item from the cache, or execute the given Closure and store the result forever.
+ *
+ * @param string $key
+ * @param \Closure $callback
+ * @return mixed
+ */
+ public function rememberForever($key, Closure $callback);
+
+ /**
+ * Remove an item from the cache.
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function forget($key);
+
+ /**
+ * Get the cache store implementation.
+ *
+ * @return \Illuminate\Contracts\Cache\Store
+ */
+ public function getStore();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Store.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Store.php
new file mode 100644
index 0000000..133bc43
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cache/Store.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace Illuminate\Contracts\Cache;
+
+interface Store
+{
+ /**
+ * Retrieve an item from the cache by key.
+ *
+ * @param string|array $key
+ * @return mixed
+ */
+ public function get($key);
+
+ /**
+ * Retrieve multiple items from the cache by key.
+ *
+ * Items not found in the cache will have a null value.
+ *
+ * @param array $keys
+ * @return array
+ */
+ public function many(array $keys);
+
+ /**
+ * Store an item in the cache for a given number of seconds.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param int $seconds
+ * @return bool
+ */
+ public function put($key, $value, $seconds);
+
+ /**
+ * Store multiple items in the cache for a given number of seconds.
+ *
+ * @param array $values
+ * @param int $seconds
+ * @return bool
+ */
+ public function putMany(array $values, $seconds);
+
+ /**
+ * Increment the value of an item in the cache.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return int|bool
+ */
+ public function increment($key, $value = 1);
+
+ /**
+ * Decrement the value of an item in the cache.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return int|bool
+ */
+ public function decrement($key, $value = 1);
+
+ /**
+ * Store an item in the cache indefinitely.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return bool
+ */
+ public function forever($key, $value);
+
+ /**
+ * Remove an item from the cache.
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function forget($key);
+
+ /**
+ * Remove all items from the cache.
+ *
+ * @return bool
+ */
+ public function flush();
+
+ /**
+ * Get the cache key prefix.
+ *
+ * @return string
+ */
+ public function getPrefix();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Config/Repository.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Config/Repository.php
new file mode 100644
index 0000000..a4f0ac8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Config/Repository.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Illuminate\Contracts\Config;
+
+interface Repository
+{
+ /**
+ * Determine if the given configuration value exists.
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function has($key);
+
+ /**
+ * Get the specified configuration value.
+ *
+ * @param array|string $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public function get($key, $default = null);
+
+ /**
+ * Get all of the configuration items for the application.
+ *
+ * @return array
+ */
+ public function all();
+
+ /**
+ * Set a given configuration value.
+ *
+ * @param array|string $key
+ * @param mixed $value
+ * @return void
+ */
+ public function set($key, $value = null);
+
+ /**
+ * Prepend a value onto an array configuration value.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return void
+ */
+ public function prepend($key, $value);
+
+ /**
+ * Push a value onto an array configuration value.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return void
+ */
+ public function push($key, $value);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Console/Application.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Console/Application.php
new file mode 100644
index 0000000..ba628c9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Console/Application.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Illuminate\Contracts\Console;
+
+interface Application
+{
+ /**
+ * Run an Artisan console command by name.
+ *
+ * @param string $command
+ * @param array $parameters
+ * @param \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer
+ * @return int
+ */
+ public function call($command, array $parameters = [], $outputBuffer = null);
+
+ /**
+ * Get the output from the last command.
+ *
+ * @return string
+ */
+ public function output();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Console/Kernel.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Console/Kernel.php
new file mode 100644
index 0000000..842f5a6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Console/Kernel.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace Illuminate\Contracts\Console;
+
+interface Kernel
+{
+ /**
+ * Bootstrap the application for artisan commands.
+ *
+ * @return void
+ */
+ public function bootstrap();
+
+ /**
+ * Handle an incoming console command.
+ *
+ * @param \Symfony\Component\Console\Input\InputInterface $input
+ * @param \Symfony\Component\Console\Output\OutputInterface|null $output
+ * @return int
+ */
+ public function handle($input, $output = null);
+
+ /**
+ * Run an Artisan console command by name.
+ *
+ * @param string $command
+ * @param array $parameters
+ * @param \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer
+ * @return int
+ */
+ public function call($command, array $parameters = [], $outputBuffer = null);
+
+ /**
+ * Queue an Artisan console command by name.
+ *
+ * @param string $command
+ * @param array $parameters
+ * @return \Illuminate\Foundation\Bus\PendingDispatch
+ */
+ public function queue($command, array $parameters = []);
+
+ /**
+ * Get all of the commands registered with the console.
+ *
+ * @return array
+ */
+ public function all();
+
+ /**
+ * Get the output for the last run command.
+ *
+ * @return string
+ */
+ public function output();
+
+ /**
+ * Terminate the application.
+ *
+ * @param \Symfony\Component\Console\Input\InputInterface $input
+ * @param int $status
+ * @return void
+ */
+ public function terminate($input, $status);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/BindingResolutionException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/BindingResolutionException.php
new file mode 100644
index 0000000..a69c24c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/BindingResolutionException.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Illuminate\Contracts\Container;
+
+use Exception;
+use Psr\Container\ContainerExceptionInterface;
+
+class BindingResolutionException extends Exception implements ContainerExceptionInterface
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/CircularDependencyException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/CircularDependencyException.php
new file mode 100644
index 0000000..6c90381
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/CircularDependencyException.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Illuminate\Contracts\Container;
+
+use Exception;
+use Psr\Container\ContainerExceptionInterface;
+
+class CircularDependencyException extends Exception implements ContainerExceptionInterface
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/Container.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/Container.php
new file mode 100644
index 0000000..1b8bb64
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/Container.php
@@ -0,0 +1,183 @@
+<?php
+
+namespace Illuminate\Contracts\Container;
+
+use Closure;
+use Psr\Container\ContainerInterface;
+
+interface Container extends ContainerInterface
+{
+ /**
+ * Determine if the given abstract type has been bound.
+ *
+ * @param string $abstract
+ * @return bool
+ */
+ public function bound($abstract);
+
+ /**
+ * Alias a type to a different name.
+ *
+ * @param string $abstract
+ * @param string $alias
+ * @return void
+ *
+ * @throws \LogicException
+ */
+ public function alias($abstract, $alias);
+
+ /**
+ * Assign a set of tags to a given binding.
+ *
+ * @param array|string $abstracts
+ * @param array|mixed ...$tags
+ * @return void
+ */
+ public function tag($abstracts, $tags);
+
+ /**
+ * Resolve all of the bindings for a given tag.
+ *
+ * @param string $tag
+ * @return iterable
+ */
+ public function tagged($tag);
+
+ /**
+ * Register a binding with the container.
+ *
+ * @param string $abstract
+ * @param \Closure|string|null $concrete
+ * @param bool $shared
+ * @return void
+ */
+ public function bind($abstract, $concrete = null, $shared = false);
+
+ /**
+ * Register a binding if it hasn't already been registered.
+ *
+ * @param string $abstract
+ * @param \Closure|string|null $concrete
+ * @param bool $shared
+ * @return void
+ */
+ public function bindIf($abstract, $concrete = null, $shared = false);
+
+ /**
+ * Register a shared binding in the container.
+ *
+ * @param string $abstract
+ * @param \Closure|string|null $concrete
+ * @return void
+ */
+ public function singleton($abstract, $concrete = null);
+
+ /**
+ * Register a shared binding if it hasn't already been registered.
+ *
+ * @param string $abstract
+ * @param \Closure|string|null $concrete
+ * @return void
+ */
+ public function singletonIf($abstract, $concrete = null);
+
+ /**
+ * "Extend" an abstract type in the container.
+ *
+ * @param string $abstract
+ * @param \Closure $closure
+ * @return void
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function extend($abstract, Closure $closure);
+
+ /**
+ * Register an existing instance as shared in the container.
+ *
+ * @param string $abstract
+ * @param mixed $instance
+ * @return mixed
+ */
+ public function instance($abstract, $instance);
+
+ /**
+ * Add a contextual binding to the container.
+ *
+ * @param string $concrete
+ * @param string $abstract
+ * @param \Closure|string $implementation
+ * @return void
+ */
+ public function addContextualBinding($concrete, $abstract, $implementation);
+
+ /**
+ * Define a contextual binding.
+ *
+ * @param string|array $concrete
+ * @return \Illuminate\Contracts\Container\ContextualBindingBuilder
+ */
+ public function when($concrete);
+
+ /**
+ * Get a closure to resolve the given type from the container.
+ *
+ * @param string $abstract
+ * @return \Closure
+ */
+ public function factory($abstract);
+
+ /**
+ * Flush the container of all bindings and resolved instances.
+ *
+ * @return void
+ */
+ public function flush();
+
+ /**
+ * Resolve the given type from the container.
+ *
+ * @param string $abstract
+ * @param array $parameters
+ * @return mixed
+ *
+ * @throws \Illuminate\Contracts\Container\BindingResolutionException
+ */
+ public function make($abstract, array $parameters = []);
+
+ /**
+ * Call the given Closure / class@method and inject its dependencies.
+ *
+ * @param callable|string $callback
+ * @param array $parameters
+ * @param string|null $defaultMethod
+ * @return mixed
+ */
+ public function call($callback, array $parameters = [], $defaultMethod = null);
+
+ /**
+ * Determine if the given abstract type has been resolved.
+ *
+ * @param string $abstract
+ * @return bool
+ */
+ public function resolved($abstract);
+
+ /**
+ * Register a new resolving callback.
+ *
+ * @param \Closure|string $abstract
+ * @param \Closure|null $callback
+ * @return void
+ */
+ public function resolving($abstract, Closure $callback = null);
+
+ /**
+ * Register a new after resolving callback.
+ *
+ * @param \Closure|string $abstract
+ * @param \Closure|null $callback
+ * @return void
+ */
+ public function afterResolving($abstract, Closure $callback = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/ContextualBindingBuilder.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/ContextualBindingBuilder.php
new file mode 100644
index 0000000..05e3625
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Container/ContextualBindingBuilder.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Illuminate\Contracts\Container;
+
+interface ContextualBindingBuilder
+{
+ /**
+ * Define the abstract target that depends on the context.
+ *
+ * @param string $abstract
+ * @return $this
+ */
+ public function needs($abstract);
+
+ /**
+ * Define the implementation for the contextual binding.
+ *
+ * @param \Closure|string $implementation
+ * @return void
+ */
+ public function give($implementation);
+
+ /**
+ * Define tagged services to be used as the implementation for the contextual binding.
+ *
+ * @param string $tag
+ * @return void
+ */
+ public function giveTagged($tag);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cookie/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cookie/Factory.php
new file mode 100644
index 0000000..6f95021
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cookie/Factory.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Illuminate\Contracts\Cookie;
+
+interface Factory
+{
+ /**
+ * Create a new cookie instance.
+ *
+ * @param string $name
+ * @param string $value
+ * @param int $minutes
+ * @param string|null $path
+ * @param string|null $domain
+ * @param bool|null $secure
+ * @param bool $httpOnly
+ * @param bool $raw
+ * @param string|null $sameSite
+ * @return \Symfony\Component\HttpFoundation\Cookie
+ */
+ public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = null, $httpOnly = true, $raw = false, $sameSite = null);
+
+ /**
+ * Create a cookie that lasts "forever" (five years).
+ *
+ * @param string $name
+ * @param string $value
+ * @param string|null $path
+ * @param string|null $domain
+ * @param bool|null $secure
+ * @param bool $httpOnly
+ * @param bool $raw
+ * @param string|null $sameSite
+ * @return \Symfony\Component\HttpFoundation\Cookie
+ */
+ public function forever($name, $value, $path = null, $domain = null, $secure = null, $httpOnly = true, $raw = false, $sameSite = null);
+
+ /**
+ * Expire the given cookie.
+ *
+ * @param string $name
+ * @param string|null $path
+ * @param string|null $domain
+ * @return \Symfony\Component\HttpFoundation\Cookie
+ */
+ public function forget($name, $path = null, $domain = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cookie/QueueingFactory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cookie/QueueingFactory.php
new file mode 100644
index 0000000..d6c74b8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Cookie/QueueingFactory.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Illuminate\Contracts\Cookie;
+
+interface QueueingFactory extends Factory
+{
+ /**
+ * Queue a cookie to send with the next response.
+ *
+ * @param array $parameters
+ * @return void
+ */
+ public function queue(...$parameters);
+
+ /**
+ * Remove a cookie from the queue.
+ *
+ * @param string $name
+ * @param string|null $path
+ * @return void
+ */
+ public function unqueue($name, $path = null);
+
+ /**
+ * Get the cookies which have been queued for the next request.
+ *
+ * @return array
+ */
+ public function getQueuedCookies();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/Castable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/Castable.php
new file mode 100644
index 0000000..911b1cf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/Castable.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Illuminate\Contracts\Database\Eloquent;
+
+interface Castable
+{
+ /**
+ * Get the name of the caster class to use when casting from / to this cast target.
+ *
+ * @param array $arguments
+ * @return string
+ * @return string|\Illuminate\Contracts\Database\Eloquent\CastsAttributes|\Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes
+ */
+ public static function castUsing(array $arguments);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/CastsAttributes.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/CastsAttributes.php
new file mode 100644
index 0000000..808d005
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/CastsAttributes.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Illuminate\Contracts\Database\Eloquent;
+
+interface CastsAttributes
+{
+ /**
+ * Transform the attribute from the underlying model values.
+ *
+ * @param \Illuminate\Database\Eloquent\Model $model
+ * @param string $key
+ * @param mixed $value
+ * @param array $attributes
+ * @return mixed
+ */
+ public function get($model, string $key, $value, array $attributes);
+
+ /**
+ * Transform the attribute to its underlying model values.
+ *
+ * @param \Illuminate\Database\Eloquent\Model $model
+ * @param string $key
+ * @param mixed $value
+ * @param array $attributes
+ * @return mixed
+ */
+ public function set($model, string $key, $value, array $attributes);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/CastsInboundAttributes.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/CastsInboundAttributes.php
new file mode 100644
index 0000000..4c7801b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/CastsInboundAttributes.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Illuminate\Contracts\Database\Eloquent;
+
+interface CastsInboundAttributes
+{
+ /**
+ * Transform the attribute to its underlying model values.
+ *
+ * @param \Illuminate\Database\Eloquent\Model $model
+ * @param string $key
+ * @param mixed $value
+ * @param array $attributes
+ * @return mixed
+ */
+ public function set($model, string $key, $value, array $attributes);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/DeviatesCastableAttributes.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/DeviatesCastableAttributes.php
new file mode 100644
index 0000000..48ba73a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/DeviatesCastableAttributes.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Illuminate\Contracts\Database\Eloquent;
+
+interface DeviatesCastableAttributes
+{
+ /**
+ * Increment the attribute.
+ *
+ * @param \Illuminate\Database\Eloquent\Model $model
+ * @param string $key
+ * @param mixed $value
+ * @param array $attributes
+ * @return mixed
+ */
+ public function increment($model, string $key, $value, array $attributes);
+
+ /**
+ * Decrement the attribute.
+ *
+ * @param \Illuminate\Database\Eloquent\Model $model
+ * @param string $key
+ * @param mixed $value
+ * @param array $attributes
+ * @return mixed
+ */
+ public function decrement($model, string $key, $value, array $attributes);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/SerializesCastableAttributes.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/SerializesCastableAttributes.php
new file mode 100644
index 0000000..a89f910
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/SerializesCastableAttributes.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Illuminate\Contracts\Database\Eloquent;
+
+interface SerializesCastableAttributes
+{
+ /**
+ * Serialize the attribute when converting the model to an array.
+ *
+ * @param \Illuminate\Database\Eloquent\Model $model
+ * @param string $key
+ * @param mixed $value
+ * @param array $attributes
+ * @return mixed
+ */
+ public function serialize($model, string $key, $value, array $attributes);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/SupportsPartialRelations.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/SupportsPartialRelations.php
new file mode 100644
index 0000000..c82125a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Eloquent/SupportsPartialRelations.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Illuminate\Contracts\Database\Eloquent;
+
+interface SupportsPartialRelations
+{
+ /**
+ * Indicate that the relation is a single result of a larger one-to-many relationship.
+ *
+ * @param string|null $column
+ * @param string|\Closure|null $aggregate
+ * @param string $relation
+ * @return $this
+ */
+ public function ofMany($column = 'id', $aggregate = 'MAX', $relation = null);
+
+ /**
+ * Determine whether the relationship is a one-of-many relationship.
+ *
+ * @return bool
+ */
+ public function isOneOfMany();
+
+ /**
+ * Get the one of many inner join subselect query builder instance.
+ *
+ * @return \Illuminate\Database\Eloquent\Builder|void
+ */
+ public function getOneOfManySubQuery();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Events/MigrationEvent.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Events/MigrationEvent.php
new file mode 100644
index 0000000..2da155f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/Events/MigrationEvent.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Illuminate\Contracts\Database\Events;
+
+interface MigrationEvent
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/ModelIdentifier.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/ModelIdentifier.php
new file mode 100644
index 0000000..9893d28
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Database/ModelIdentifier.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Illuminate\Contracts\Database;
+
+class ModelIdentifier
+{
+ /**
+ * The class name of the model.
+ *
+ * @var string
+ */
+ public $class;
+
+ /**
+ * The unique identifier of the model.
+ *
+ * This may be either a single ID or an array of IDs.
+ *
+ * @var mixed
+ */
+ public $id;
+
+ /**
+ * The relationships loaded on the model.
+ *
+ * @var array
+ */
+ public $relations;
+
+ /**
+ * The connection name of the model.
+ *
+ * @var string|null
+ */
+ public $connection;
+
+ /**
+ * Create a new model identifier.
+ *
+ * @param string $class
+ * @param mixed $id
+ * @param array $relations
+ * @param mixed $connection
+ * @return void
+ */
+ public function __construct($class, $id, array $relations, $connection)
+ {
+ $this->id = $id;
+ $this->class = $class;
+ $this->relations = $relations;
+ $this->connection = $connection;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Debug/ExceptionHandler.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Debug/ExceptionHandler.php
new file mode 100644
index 0000000..54381a1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Debug/ExceptionHandler.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace Illuminate\Contracts\Debug;
+
+use Throwable;
+
+interface ExceptionHandler
+{
+ /**
+ * Report or log an exception.
+ *
+ * @param \Throwable $e
+ * @return void
+ *
+ * @throws \Throwable
+ */
+ public function report(Throwable $e);
+
+ /**
+ * Determine if the exception should be reported.
+ *
+ * @param \Throwable $e
+ * @return bool
+ */
+ public function shouldReport(Throwable $e);
+
+ /**
+ * Render an exception into an HTTP response.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @param \Throwable $e
+ * @return \Symfony\Component\HttpFoundation\Response
+ *
+ * @throws \Throwable
+ */
+ public function render($request, Throwable $e);
+
+ /**
+ * Render an exception to the console.
+ *
+ * @param \Symfony\Component\Console\Output\OutputInterface $output
+ * @param \Throwable $e
+ * @return void
+ */
+ public function renderForConsole($output, Throwable $e);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/DecryptException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/DecryptException.php
new file mode 100644
index 0000000..7edebc9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/DecryptException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Illuminate\Contracts\Encryption;
+
+use RuntimeException;
+
+class DecryptException extends RuntimeException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/EncryptException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/EncryptException.php
new file mode 100644
index 0000000..2146ee0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/EncryptException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Illuminate\Contracts\Encryption;
+
+use RuntimeException;
+
+class EncryptException extends RuntimeException
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/Encrypter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/Encrypter.php
new file mode 100644
index 0000000..4747b68
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/Encrypter.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Illuminate\Contracts\Encryption;
+
+interface Encrypter
+{
+ /**
+ * Encrypt the given value.
+ *
+ * @param mixed $value
+ * @param bool $serialize
+ * @return string
+ *
+ * @throws \Illuminate\Contracts\Encryption\EncryptException
+ */
+ public function encrypt($value, $serialize = true);
+
+ /**
+ * Decrypt the given value.
+ *
+ * @param string $payload
+ * @param bool $unserialize
+ * @return mixed
+ *
+ * @throws \Illuminate\Contracts\Encryption\DecryptException
+ */
+ public function decrypt($payload, $unserialize = true);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/StringEncrypter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/StringEncrypter.php
new file mode 100644
index 0000000..1e6938c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Encryption/StringEncrypter.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Illuminate\Contracts\Encryption;
+
+interface StringEncrypter
+{
+ /**
+ * Encrypt a string without serialization.
+ *
+ * @param string $value
+ * @return string
+ *
+ * @throws \Illuminate\Contracts\Encryption\EncryptException
+ */
+ public function encryptString($value);
+
+ /**
+ * Decrypt the given string without unserialization.
+ *
+ * @param string $payload
+ * @return string
+ *
+ * @throws \Illuminate\Contracts\Encryption\DecryptException
+ */
+ public function decryptString($payload);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Events/Dispatcher.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Events/Dispatcher.php
new file mode 100644
index 0000000..6386106
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Events/Dispatcher.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace Illuminate\Contracts\Events;
+
+interface Dispatcher
+{
+ /**
+ * Register an event listener with the dispatcher.
+ *
+ * @param \Closure|string|array $events
+ * @param \Closure|string|array|null $listener
+ * @return void
+ */
+ public function listen($events, $listener = null);
+
+ /**
+ * Determine if a given event has listeners.
+ *
+ * @param string $eventName
+ * @return bool
+ */
+ public function hasListeners($eventName);
+
+ /**
+ * Register an event subscriber with the dispatcher.
+ *
+ * @param object|string $subscriber
+ * @return void
+ */
+ public function subscribe($subscriber);
+
+ /**
+ * Dispatch an event until the first non-null response is returned.
+ *
+ * @param string|object $event
+ * @param mixed $payload
+ * @return array|null
+ */
+ public function until($event, $payload = []);
+
+ /**
+ * Dispatch an event and call the listeners.
+ *
+ * @param string|object $event
+ * @param mixed $payload
+ * @param bool $halt
+ * @return array|null
+ */
+ public function dispatch($event, $payload = [], $halt = false);
+
+ /**
+ * Register an event and payload to be fired later.
+ *
+ * @param string $event
+ * @param array $payload
+ * @return void
+ */
+ public function push($event, $payload = []);
+
+ /**
+ * Flush a set of pushed events.
+ *
+ * @param string $event
+ * @return void
+ */
+ public function flush($event);
+
+ /**
+ * Remove a set of listeners from the dispatcher.
+ *
+ * @param string $event
+ * @return void
+ */
+ public function forget($event);
+
+ /**
+ * Forget all of the queued listeners.
+ *
+ * @return void
+ */
+ public function forgetPushed();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/Cloud.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/Cloud.php
new file mode 100644
index 0000000..86bea26
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/Cloud.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Filesystem;
+
+interface Cloud extends Filesystem
+{
+ /**
+ * Get the URL for the file at the given path.
+ *
+ * @param string $path
+ * @return string
+ */
+ public function url($path);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/Factory.php
new file mode 100644
index 0000000..d0f9cd2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/Factory.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Filesystem;
+
+interface Factory
+{
+ /**
+ * Get a filesystem implementation.
+ *
+ * @param string|null $name
+ * @return \Illuminate\Contracts\Filesystem\Filesystem
+ */
+ public function disk($name = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/FileExistsException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/FileExistsException.php
new file mode 100644
index 0000000..9027892
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/FileExistsException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Illuminate\Contracts\Filesystem;
+
+use Exception;
+
+class FileExistsException extends Exception
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/FileNotFoundException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/FileNotFoundException.php
new file mode 100644
index 0000000..37b7930
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/FileNotFoundException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Illuminate\Contracts\Filesystem;
+
+use Exception;
+
+class FileNotFoundException extends Exception
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/Filesystem.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/Filesystem.php
new file mode 100644
index 0000000..e8b0dd4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/Filesystem.php
@@ -0,0 +1,198 @@
+<?php
+
+namespace Illuminate\Contracts\Filesystem;
+
+interface Filesystem
+{
+ /**
+ * The public visibility setting.
+ *
+ * @var string
+ */
+ const VISIBILITY_PUBLIC = 'public';
+
+ /**
+ * The private visibility setting.
+ *
+ * @var string
+ */
+ const VISIBILITY_PRIVATE = 'private';
+
+ /**
+ * Determine if a file exists.
+ *
+ * @param string $path
+ * @return bool
+ */
+ public function exists($path);
+
+ /**
+ * Get the contents of a file.
+ *
+ * @param string $path
+ * @return string
+ *
+ * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
+ */
+ public function get($path);
+
+ /**
+ * Get a resource to read the file.
+ *
+ * @param string $path
+ * @return resource|null The path resource or null on failure.
+ *
+ * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
+ */
+ public function readStream($path);
+
+ /**
+ * Write the contents of a file.
+ *
+ * @param string $path
+ * @param string|resource $contents
+ * @param mixed $options
+ * @return bool
+ */
+ public function put($path, $contents, $options = []);
+
+ /**
+ * Write a new file using a stream.
+ *
+ * @param string $path
+ * @param resource $resource
+ * @param array $options
+ * @return bool
+ *
+ * @throws \InvalidArgumentException If $resource is not a file handle.
+ * @throws \Illuminate\Contracts\Filesystem\FileExistsException
+ */
+ public function writeStream($path, $resource, array $options = []);
+
+ /**
+ * Get the visibility for the given path.
+ *
+ * @param string $path
+ * @return string
+ */
+ public function getVisibility($path);
+
+ /**
+ * Set the visibility for the given path.
+ *
+ * @param string $path
+ * @param string $visibility
+ * @return bool
+ */
+ public function setVisibility($path, $visibility);
+
+ /**
+ * Prepend to a file.
+ *
+ * @param string $path
+ * @param string $data
+ * @return bool
+ */
+ public function prepend($path, $data);
+
+ /**
+ * Append to a file.
+ *
+ * @param string $path
+ * @param string $data
+ * @return bool
+ */
+ public function append($path, $data);
+
+ /**
+ * Delete the file at a given path.
+ *
+ * @param string|array $paths
+ * @return bool
+ */
+ public function delete($paths);
+
+ /**
+ * Copy a file to a new location.
+ *
+ * @param string $from
+ * @param string $to
+ * @return bool
+ */
+ public function copy($from, $to);
+
+ /**
+ * Move a file to a new location.
+ *
+ * @param string $from
+ * @param string $to
+ * @return bool
+ */
+ public function move($from, $to);
+
+ /**
+ * Get the file size of a given file.
+ *
+ * @param string $path
+ * @return int
+ */
+ public function size($path);
+
+ /**
+ * Get the file's last modification time.
+ *
+ * @param string $path
+ * @return int
+ */
+ public function lastModified($path);
+
+ /**
+ * Get an array of all files in a directory.
+ *
+ * @param string|null $directory
+ * @param bool $recursive
+ * @return array
+ */
+ public function files($directory = null, $recursive = false);
+
+ /**
+ * Get all of the files from the given directory (recursive).
+ *
+ * @param string|null $directory
+ * @return array
+ */
+ public function allFiles($directory = null);
+
+ /**
+ * Get all of the directories within a given directory.
+ *
+ * @param string|null $directory
+ * @param bool $recursive
+ * @return array
+ */
+ public function directories($directory = null, $recursive = false);
+
+ /**
+ * Get all (recursive) of the directories within a given directory.
+ *
+ * @param string|null $directory
+ * @return array
+ */
+ public function allDirectories($directory = null);
+
+ /**
+ * Create a directory.
+ *
+ * @param string $path
+ * @return bool
+ */
+ public function makeDirectory($path);
+
+ /**
+ * Recursively delete a directory.
+ *
+ * @param string $directory
+ * @return bool
+ */
+ public function deleteDirectory($directory);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/LockTimeoutException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/LockTimeoutException.php
new file mode 100644
index 0000000..f03f5c4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Filesystem/LockTimeoutException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Illuminate\Contracts\Filesystem;
+
+use Exception;
+
+class LockTimeoutException extends Exception
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Foundation/Application.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Foundation/Application.php
new file mode 100644
index 0000000..8ae0a31
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Foundation/Application.php
@@ -0,0 +1,215 @@
+<?php
+
+namespace Illuminate\Contracts\Foundation;
+
+use Illuminate\Contracts\Container\Container;
+
+interface Application extends Container
+{
+ /**
+ * Get the version number of the application.
+ *
+ * @return string
+ */
+ public function version();
+
+ /**
+ * Get the base path of the Laravel installation.
+ *
+ * @param string $path
+ * @return string
+ */
+ public function basePath($path = '');
+
+ /**
+ * Get the path to the bootstrap directory.
+ *
+ * @param string $path Optionally, a path to append to the bootstrap path
+ * @return string
+ */
+ public function bootstrapPath($path = '');
+
+ /**
+ * Get the path to the application configuration files.
+ *
+ * @param string $path Optionally, a path to append to the config path
+ * @return string
+ */
+ public function configPath($path = '');
+
+ /**
+ * Get the path to the database directory.
+ *
+ * @param string $path Optionally, a path to append to the database path
+ * @return string
+ */
+ public function databasePath($path = '');
+
+ /**
+ * Get the path to the resources directory.
+ *
+ * @param string $path
+ * @return string
+ */
+ public function resourcePath($path = '');
+
+ /**
+ * Get the path to the storage directory.
+ *
+ * @return string
+ */
+ public function storagePath();
+
+ /**
+ * Get or check the current application environment.
+ *
+ * @param string|array $environments
+ * @return string|bool
+ */
+ public function environment(...$environments);
+
+ /**
+ * Determine if the application is running in the console.
+ *
+ * @return bool
+ */
+ public function runningInConsole();
+
+ /**
+ * Determine if the application is running unit tests.
+ *
+ * @return bool
+ */
+ public function runningUnitTests();
+
+ /**
+ * Determine if the application is currently down for maintenance.
+ *
+ * @return bool
+ */
+ public function isDownForMaintenance();
+
+ /**
+ * Register all of the configured providers.
+ *
+ * @return void
+ */
+ public function registerConfiguredProviders();
+
+ /**
+ * Register a service provider with the application.
+ *
+ * @param \Illuminate\Support\ServiceProvider|string $provider
+ * @param bool $force
+ * @return \Illuminate\Support\ServiceProvider
+ */
+ public function register($provider, $force = false);
+
+ /**
+ * Register a deferred provider and service.
+ *
+ * @param string $provider
+ * @param string|null $service
+ * @return void
+ */
+ public function registerDeferredProvider($provider, $service = null);
+
+ /**
+ * Resolve a service provider instance from the class name.
+ *
+ * @param string $provider
+ * @return \Illuminate\Support\ServiceProvider
+ */
+ public function resolveProvider($provider);
+
+ /**
+ * Boot the application's service providers.
+ *
+ * @return void
+ */
+ public function boot();
+
+ /**
+ * Register a new boot listener.
+ *
+ * @param callable $callback
+ * @return void
+ */
+ public function booting($callback);
+
+ /**
+ * Register a new "booted" listener.
+ *
+ * @param callable $callback
+ * @return void
+ */
+ public function booted($callback);
+
+ /**
+ * Run the given array of bootstrap classes.
+ *
+ * @param array $bootstrappers
+ * @return void
+ */
+ public function bootstrapWith(array $bootstrappers);
+
+ /**
+ * Get the current application locale.
+ *
+ * @return string
+ */
+ public function getLocale();
+
+ /**
+ * Get the application namespace.
+ *
+ * @return string
+ *
+ * @throws \RuntimeException
+ */
+ public function getNamespace();
+
+ /**
+ * Get the registered service provider instances if any exist.
+ *
+ * @param \Illuminate\Support\ServiceProvider|string $provider
+ * @return array
+ */
+ public function getProviders($provider);
+
+ /**
+ * Determine if the application has been bootstrapped before.
+ *
+ * @return bool
+ */
+ public function hasBeenBootstrapped();
+
+ /**
+ * Load and boot all of the remaining deferred providers.
+ *
+ * @return void
+ */
+ public function loadDeferredProviders();
+
+ /**
+ * Set the current application locale.
+ *
+ * @param string $locale
+ * @return void
+ */
+ public function setLocale($locale);
+
+ /**
+ * Determine if middleware has been disabled for the application.
+ *
+ * @return bool
+ */
+ public function shouldSkipMiddleware();
+
+ /**
+ * Terminate the application.
+ *
+ * @return void
+ */
+ public function terminate();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Foundation/CachesConfiguration.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Foundation/CachesConfiguration.php
new file mode 100644
index 0000000..08ebdaf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Foundation/CachesConfiguration.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Illuminate\Contracts\Foundation;
+
+interface CachesConfiguration
+{
+ /**
+ * Determine if the application configuration is cached.
+ *
+ * @return bool
+ */
+ public function configurationIsCached();
+
+ /**
+ * Get the path to the configuration cache file.
+ *
+ * @return string
+ */
+ public function getCachedConfigPath();
+
+ /**
+ * Get the path to the cached services.php file.
+ *
+ * @return string
+ */
+ public function getCachedServicesPath();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Foundation/CachesRoutes.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Foundation/CachesRoutes.php
new file mode 100644
index 0000000..a5c3455
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Foundation/CachesRoutes.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Illuminate\Contracts\Foundation;
+
+interface CachesRoutes
+{
+ /**
+ * Determine if the application routes are cached.
+ *
+ * @return bool
+ */
+ public function routesAreCached();
+
+ /**
+ * Get the path to the routes cache file.
+ *
+ * @return string
+ */
+ public function getCachedRoutesPath();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Hashing/Hasher.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Hashing/Hasher.php
new file mode 100644
index 0000000..b5e4d4c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Hashing/Hasher.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace Illuminate\Contracts\Hashing;
+
+interface Hasher
+{
+ /**
+ * Get information about the given hashed value.
+ *
+ * @param string $hashedValue
+ * @return array
+ */
+ public function info($hashedValue);
+
+ /**
+ * Hash the given value.
+ *
+ * @param string $value
+ * @param array $options
+ * @return string
+ */
+ public function make($value, array $options = []);
+
+ /**
+ * Check the given plain value against a hash.
+ *
+ * @param string $value
+ * @param string $hashedValue
+ * @param array $options
+ * @return bool
+ */
+ public function check($value, $hashedValue, array $options = []);
+
+ /**
+ * Check if the given hash has been hashed using the given options.
+ *
+ * @param string $hashedValue
+ * @param array $options
+ * @return bool
+ */
+ public function needsRehash($hashedValue, array $options = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Http/Kernel.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Http/Kernel.php
new file mode 100644
index 0000000..6eab6e6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Http/Kernel.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Illuminate\Contracts\Http;
+
+interface Kernel
+{
+ /**
+ * Bootstrap the application for HTTP requests.
+ *
+ * @return void
+ */
+ public function bootstrap();
+
+ /**
+ * Handle an incoming HTTP request.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * @return \Symfony\Component\HttpFoundation\Response
+ */
+ public function handle($request);
+
+ /**
+ * Perform any final actions for the request lifecycle.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * @param \Symfony\Component\HttpFoundation\Response $response
+ * @return void
+ */
+ public function terminate($request, $response);
+
+ /**
+ * Get the Laravel application instance.
+ *
+ * @return \Illuminate\Contracts\Foundation\Application
+ */
+ public function getApplication();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/LICENSE.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/LICENSE.md
new file mode 100644
index 0000000..79810c8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/LICENSE.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Taylor Otwell
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/Factory.php
new file mode 100644
index 0000000..fe45a2f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/Factory.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Mail;
+
+interface Factory
+{
+ /**
+ * Get a mailer instance by name.
+ *
+ * @param string|null $name
+ * @return \Illuminate\Contracts\Mail\Mailer
+ */
+ public function mailer($name = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/MailQueue.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/MailQueue.php
new file mode 100644
index 0000000..d0d90b8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/MailQueue.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Illuminate\Contracts\Mail;
+
+interface MailQueue
+{
+ /**
+ * Queue a new e-mail message for sending.
+ *
+ * @param \Illuminate\Contracts\Mail\Mailable|string|array $view
+ * @param string|null $queue
+ * @return mixed
+ */
+ public function queue($view, $queue = null);
+
+ /**
+ * Queue a new e-mail message for sending after (n) seconds.
+ *
+ * @param \DateTimeInterface|\DateInterval|int $delay
+ * @param \Illuminate\Contracts\Mail\Mailable|string|array $view
+ * @param string|null $queue
+ * @return mixed
+ */
+ public function later($delay, $view, $queue = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/Mailable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/Mailable.php
new file mode 100644
index 0000000..bfdf4ef
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/Mailable.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Illuminate\Contracts\Mail;
+
+use Illuminate\Contracts\Queue\Factory as Queue;
+
+interface Mailable
+{
+ /**
+ * Send the message using the given mailer.
+ *
+ * @param \Illuminate\Contracts\Mail\Factory|\Illuminate\Contracts\Mail\Mailer $mailer
+ * @return void
+ */
+ public function send($mailer);
+
+ /**
+ * Queue the given message.
+ *
+ * @param \Illuminate\Contracts\Queue\Factory $queue
+ * @return mixed
+ */
+ public function queue(Queue $queue);
+
+ /**
+ * Deliver the queued message after the given delay.
+ *
+ * @param \DateTimeInterface|\DateInterval|int $delay
+ * @param \Illuminate\Contracts\Queue\Factory $queue
+ * @return mixed
+ */
+ public function later($delay, Queue $queue);
+
+ /**
+ * Set the recipients of the message.
+ *
+ * @param object|array|string $address
+ * @param string|null $name
+ * @return self
+ */
+ public function cc($address, $name = null);
+
+ /**
+ * Set the recipients of the message.
+ *
+ * @param object|array|string $address
+ * @param string|null $name
+ * @return $this
+ */
+ public function bcc($address, $name = null);
+
+ /**
+ * Set the recipients of the message.
+ *
+ * @param object|array|string $address
+ * @param string|null $name
+ * @return $this
+ */
+ public function to($address, $name = null);
+
+ /**
+ * Set the locale of the message.
+ *
+ * @param string $locale
+ * @return $this
+ */
+ public function locale($locale);
+
+ /**
+ * Set the name of the mailer that should be used to send the message.
+ *
+ * @param string $mailer
+ * @return $this
+ */
+ public function mailer($mailer);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/Mailer.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/Mailer.php
new file mode 100644
index 0000000..255b678
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Mail/Mailer.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Illuminate\Contracts\Mail;
+
+interface Mailer
+{
+ /**
+ * Begin the process of mailing a mailable class instance.
+ *
+ * @param mixed $users
+ * @return \Illuminate\Mail\PendingMail
+ */
+ public function to($users);
+
+ /**
+ * Begin the process of mailing a mailable class instance.
+ *
+ * @param mixed $users
+ * @return \Illuminate\Mail\PendingMail
+ */
+ public function bcc($users);
+
+ /**
+ * Send a new message with only a raw text part.
+ *
+ * @param string $text
+ * @param mixed $callback
+ * @return void
+ */
+ public function raw($text, $callback);
+
+ /**
+ * Send a new message using a view.
+ *
+ * @param \Illuminate\Contracts\Mail\Mailable|string|array $view
+ * @param array $data
+ * @param \Closure|string|null $callback
+ * @return void
+ */
+ public function send($view, array $data = [], $callback = null);
+
+ /**
+ * Get the array of failed recipients.
+ *
+ * @return array
+ */
+ public function failures();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Notifications/Dispatcher.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Notifications/Dispatcher.php
new file mode 100644
index 0000000..a483ca2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Notifications/Dispatcher.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Illuminate\Contracts\Notifications;
+
+interface Dispatcher
+{
+ /**
+ * Send the given notification to the given notifiable entities.
+ *
+ * @param \Illuminate\Support\Collection|array|mixed $notifiables
+ * @param mixed $notification
+ * @return void
+ */
+ public function send($notifiables, $notification);
+
+ /**
+ * Send the given notification immediately.
+ *
+ * @param \Illuminate\Support\Collection|array|mixed $notifiables
+ * @param mixed $notification
+ * @return void
+ */
+ public function sendNow($notifiables, $notification);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Notifications/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Notifications/Factory.php
new file mode 100644
index 0000000..7705678
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Notifications/Factory.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Illuminate\Contracts\Notifications;
+
+interface Factory
+{
+ /**
+ * Get a channel instance by name.
+ *
+ * @param string|null $name
+ * @return mixed
+ */
+ public function channel($name = null);
+
+ /**
+ * Send the given notification to the given notifiable entities.
+ *
+ * @param \Illuminate\Support\Collection|array|mixed $notifiables
+ * @param mixed $notification
+ * @return void
+ */
+ public function send($notifiables, $notification);
+
+ /**
+ * Send the given notification immediately.
+ *
+ * @param \Illuminate\Support\Collection|array|mixed $notifiables
+ * @param mixed $notification
+ * @return void
+ */
+ public function sendNow($notifiables, $notification);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pagination/CursorPaginator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pagination/CursorPaginator.php
new file mode 100644
index 0000000..2d62d3a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pagination/CursorPaginator.php
@@ -0,0 +1,117 @@
+<?php
+
+namespace Illuminate\Contracts\Pagination;
+
+interface CursorPaginator
+{
+ /**
+ * Get the URL for a given cursor.
+ *
+ * @param \Illuminate\Pagination\Cursor|null $cursor
+ * @return string
+ */
+ public function url($cursor);
+
+ /**
+ * Add a set of query string values to the paginator.
+ *
+ * @param array|string|null $key
+ * @param string|null $value
+ * @return $this
+ */
+ public function appends($key, $value = null);
+
+ /**
+ * Get / set the URL fragment to be appended to URLs.
+ *
+ * @param string|null $fragment
+ * @return $this|string|null
+ */
+ public function fragment($fragment = null);
+
+ /**
+ * Get the URL for the previous page, or null.
+ *
+ * @return string|null
+ */
+ public function previousPageUrl();
+
+ /**
+ * The URL for the next page, or null.
+ *
+ * @return string|null
+ */
+ public function nextPageUrl();
+
+ /**
+ * Get all of the items being paginated.
+ *
+ * @return array
+ */
+ public function items();
+
+ /**
+ * Get the "cursor" of the previous set of items.
+ *
+ * @return \Illuminate\Pagination\Cursor|null
+ */
+ public function previousCursor();
+
+ /**
+ * Get the "cursor" of the next set of items.
+ *
+ * @return \Illuminate\Pagination\Cursor|null
+ */
+ public function nextCursor();
+
+ /**
+ * Determine how many items are being shown per page.
+ *
+ * @return int
+ */
+ public function perPage();
+
+ /**
+ * Get the current cursor being paginated.
+ *
+ * @return \Illuminate\Pagination\Cursor|null
+ */
+ public function cursor();
+
+ /**
+ * Determine if there are enough items to split into multiple pages.
+ *
+ * @return bool
+ */
+ public function hasPages();
+
+ /**
+ * Get the base path for paginator generated URLs.
+ *
+ * @return string|null
+ */
+ public function path();
+
+ /**
+ * Determine if the list of items is empty or not.
+ *
+ * @return bool
+ */
+ public function isEmpty();
+
+ /**
+ * Determine if the list of items is not empty.
+ *
+ * @return bool
+ */
+ public function isNotEmpty();
+
+ /**
+ * Render the paginator using a given view.
+ *
+ * @param string|null $view
+ * @param array $data
+ * @return string
+ */
+ public function render($view = null, $data = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pagination/LengthAwarePaginator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pagination/LengthAwarePaginator.php
new file mode 100644
index 0000000..4e6ef71
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pagination/LengthAwarePaginator.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Illuminate\Contracts\Pagination;
+
+interface LengthAwarePaginator extends Paginator
+{
+ /**
+ * Create a range of pagination URLs.
+ *
+ * @param int $start
+ * @param int $end
+ * @return array
+ */
+ public function getUrlRange($start, $end);
+
+ /**
+ * Determine the total number of items in the data store.
+ *
+ * @return int
+ */
+ public function total();
+
+ /**
+ * Get the page number of the last available page.
+ *
+ * @return int
+ */
+ public function lastPage();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pagination/Paginator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pagination/Paginator.php
new file mode 100644
index 0000000..49bafaa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pagination/Paginator.php
@@ -0,0 +1,124 @@
+<?php
+
+namespace Illuminate\Contracts\Pagination;
+
+interface Paginator
+{
+ /**
+ * Get the URL for a given page.
+ *
+ * @param int $page
+ * @return string
+ */
+ public function url($page);
+
+ /**
+ * Add a set of query string values to the paginator.
+ *
+ * @param array|string $key
+ * @param string|null $value
+ * @return $this
+ */
+ public function appends($key, $value = null);
+
+ /**
+ * Get / set the URL fragment to be appended to URLs.
+ *
+ * @param string|null $fragment
+ * @return $this|string
+ */
+ public function fragment($fragment = null);
+
+ /**
+ * The URL for the next page, or null.
+ *
+ * @return string|null
+ */
+ public function nextPageUrl();
+
+ /**
+ * Get the URL for the previous page, or null.
+ *
+ * @return string|null
+ */
+ public function previousPageUrl();
+
+ /**
+ * Get all of the items being paginated.
+ *
+ * @return array
+ */
+ public function items();
+
+ /**
+ * Get the "index" of the first item being paginated.
+ *
+ * @return int
+ */
+ public function firstItem();
+
+ /**
+ * Get the "index" of the last item being paginated.
+ *
+ * @return int
+ */
+ public function lastItem();
+
+ /**
+ * Determine how many items are being shown per page.
+ *
+ * @return int
+ */
+ public function perPage();
+
+ /**
+ * Determine the current page being paginated.
+ *
+ * @return int
+ */
+ public function currentPage();
+
+ /**
+ * Determine if there are enough items to split into multiple pages.
+ *
+ * @return bool
+ */
+ public function hasPages();
+
+ /**
+ * Determine if there are more items in the data store.
+ *
+ * @return bool
+ */
+ public function hasMorePages();
+
+ /**
+ * Get the base path for paginator generated URLs.
+ *
+ * @return string|null
+ */
+ public function path();
+
+ /**
+ * Determine if the list of items is empty or not.
+ *
+ * @return bool
+ */
+ public function isEmpty();
+
+ /**
+ * Determine if the list of items is not empty.
+ *
+ * @return bool
+ */
+ public function isNotEmpty();
+
+ /**
+ * Render the paginator using a given view.
+ *
+ * @param string|null $view
+ * @param array $data
+ * @return string
+ */
+ public function render($view = null, $data = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pipeline/Hub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pipeline/Hub.php
new file mode 100644
index 0000000..1ae675f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pipeline/Hub.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Illuminate\Contracts\Pipeline;
+
+interface Hub
+{
+ /**
+ * Send an object through one of the available pipelines.
+ *
+ * @param mixed $object
+ * @param string|null $pipeline
+ * @return mixed
+ */
+ public function pipe($object, $pipeline = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pipeline/Pipeline.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pipeline/Pipeline.php
new file mode 100644
index 0000000..226081c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Pipeline/Pipeline.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Illuminate\Contracts\Pipeline;
+
+use Closure;
+
+interface Pipeline
+{
+ /**
+ * Set the traveler object being sent on the pipeline.
+ *
+ * @param mixed $traveler
+ * @return $this
+ */
+ public function send($traveler);
+
+ /**
+ * Set the stops of the pipeline.
+ *
+ * @param dynamic|array $stops
+ * @return $this
+ */
+ public function through($stops);
+
+ /**
+ * Set the method to call on the stops.
+ *
+ * @param string $method
+ * @return $this
+ */
+ public function via($method);
+
+ /**
+ * Run the pipeline with a final destination callback.
+ *
+ * @param \Closure $destination
+ * @return mixed
+ */
+ public function then(Closure $destination);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ClearableQueue.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ClearableQueue.php
new file mode 100644
index 0000000..427f61b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ClearableQueue.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface ClearableQueue
+{
+ /**
+ * Delete all of the jobs from the queue.
+ *
+ * @param string $queue
+ * @return int
+ */
+ public function clear($queue);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/EntityNotFoundException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/EntityNotFoundException.php
new file mode 100644
index 0000000..079250d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/EntityNotFoundException.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+use InvalidArgumentException;
+
+class EntityNotFoundException extends InvalidArgumentException
+{
+ /**
+ * Create a new exception instance.
+ *
+ * @param string $type
+ * @param mixed $id
+ * @return void
+ */
+ public function __construct($type, $id)
+ {
+ $id = (string) $id;
+
+ parent::__construct("Queueable entity [{$type}] not found for ID [{$id}].");
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/EntityResolver.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/EntityResolver.php
new file mode 100644
index 0000000..aad97a1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/EntityResolver.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface EntityResolver
+{
+ /**
+ * Resolve the entity for the given ID.
+ *
+ * @param string $type
+ * @param mixed $id
+ * @return mixed
+ */
+ public function resolve($type, $id);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Factory.php
new file mode 100644
index 0000000..9a0bdeb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Factory.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface Factory
+{
+ /**
+ * Resolve a queue connection instance.
+ *
+ * @param string|null $name
+ * @return \Illuminate\Contracts\Queue\Queue
+ */
+ public function connection($name = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Job.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Job.php
new file mode 100644
index 0000000..c856215
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Job.php
@@ -0,0 +1,166 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface Job
+{
+ /**
+ * Get the UUID of the job.
+ *
+ * @return string|null
+ */
+ public function uuid();
+
+ /**
+ * Get the job identifier.
+ *
+ * @return string
+ */
+ public function getJobId();
+
+ /**
+ * Get the decoded body of the job.
+ *
+ * @return array
+ */
+ public function payload();
+
+ /**
+ * Fire the job.
+ *
+ * @return void
+ */
+ public function fire();
+
+ /**
+ * Release the job back into the queue.
+ *
+ * Accepts a delay specified in seconds.
+ *
+ * @param int $delay
+ * @return void
+ */
+ public function release($delay = 0);
+
+ /**
+ * Determine if the job was released back into the queue.
+ *
+ * @return bool
+ */
+ public function isReleased();
+
+ /**
+ * Delete the job from the queue.
+ *
+ * @return void
+ */
+ public function delete();
+
+ /**
+ * Determine if the job has been deleted.
+ *
+ * @return bool
+ */
+ public function isDeleted();
+
+ /**
+ * Determine if the job has been deleted or released.
+ *
+ * @return bool
+ */
+ public function isDeletedOrReleased();
+
+ /**
+ * Get the number of times the job has been attempted.
+ *
+ * @return int
+ */
+ public function attempts();
+
+ /**
+ * Determine if the job has been marked as a failure.
+ *
+ * @return bool
+ */
+ public function hasFailed();
+
+ /**
+ * Mark the job as "failed".
+ *
+ * @return void
+ */
+ public function markAsFailed();
+
+ /**
+ * Delete the job, call the "failed" method, and raise the failed job event.
+ *
+ * @param \Throwable|null $e
+ * @return void
+ */
+ public function fail($e = null);
+
+ /**
+ * Get the number of times to attempt a job.
+ *
+ * @return int|null
+ */
+ public function maxTries();
+
+ /**
+ * Get the maximum number of exceptions allowed, regardless of attempts.
+ *
+ * @return int|null
+ */
+ public function maxExceptions();
+
+ /**
+ * Get the number of seconds the job can run.
+ *
+ * @return int|null
+ */
+ public function timeout();
+
+ /**
+ * Get the timestamp indicating when the job should timeout.
+ *
+ * @return int|null
+ */
+ public function retryUntil();
+
+ /**
+ * Get the name of the queued job class.
+ *
+ * @return string
+ */
+ public function getName();
+
+ /**
+ * Get the resolved name of the queued job class.
+ *
+ * Resolves the name of "wrapped" jobs such as class-based handlers.
+ *
+ * @return string
+ */
+ public function resolveName();
+
+ /**
+ * Get the name of the connection the job belongs to.
+ *
+ * @return string
+ */
+ public function getConnectionName();
+
+ /**
+ * Get the name of the queue the job belongs to.
+ *
+ * @return string
+ */
+ public function getQueue();
+
+ /**
+ * Get the raw body string for the job.
+ *
+ * @return string
+ */
+ public function getRawBody();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Monitor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Monitor.php
new file mode 100644
index 0000000..7da62d3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Monitor.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface Monitor
+{
+ /**
+ * Register a callback to be executed on every iteration through the queue loop.
+ *
+ * @param mixed $callback
+ * @return void
+ */
+ public function looping($callback);
+
+ /**
+ * Register a callback to be executed when a job fails after the maximum amount of retries.
+ *
+ * @param mixed $callback
+ * @return void
+ */
+ public function failing($callback);
+
+ /**
+ * Register a callback to be executed when a daemon queue is stopping.
+ *
+ * @param mixed $callback
+ * @return void
+ */
+ public function stopping($callback);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Queue.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Queue.php
new file mode 100644
index 0000000..073b3c1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/Queue.php
@@ -0,0 +1,99 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface Queue
+{
+ /**
+ * Get the size of the queue.
+ *
+ * @param string|null $queue
+ * @return int
+ */
+ public function size($queue = null);
+
+ /**
+ * Push a new job onto the queue.
+ *
+ * @param string|object $job
+ * @param mixed $data
+ * @param string|null $queue
+ * @return mixed
+ */
+ public function push($job, $data = '', $queue = null);
+
+ /**
+ * Push a new job onto the queue.
+ *
+ * @param string $queue
+ * @param string|object $job
+ * @param mixed $data
+ * @return mixed
+ */
+ public function pushOn($queue, $job, $data = '');
+
+ /**
+ * Push a raw payload onto the queue.
+ *
+ * @param string $payload
+ * @param string|null $queue
+ * @param array $options
+ * @return mixed
+ */
+ public function pushRaw($payload, $queue = null, array $options = []);
+
+ /**
+ * Push a new job onto the queue after a delay.
+ *
+ * @param \DateTimeInterface|\DateInterval|int $delay
+ * @param string|object $job
+ * @param mixed $data
+ * @param string|null $queue
+ * @return mixed
+ */
+ public function later($delay, $job, $data = '', $queue = null);
+
+ /**
+ * Push a new job onto the queue after a delay.
+ *
+ * @param string $queue
+ * @param \DateTimeInterface|\DateInterval|int $delay
+ * @param string|object $job
+ * @param mixed $data
+ * @return mixed
+ */
+ public function laterOn($queue, $delay, $job, $data = '');
+
+ /**
+ * Push an array of jobs onto the queue.
+ *
+ * @param array $jobs
+ * @param mixed $data
+ * @param string|null $queue
+ * @return mixed
+ */
+ public function bulk($jobs, $data = '', $queue = null);
+
+ /**
+ * Pop the next job off of the queue.
+ *
+ * @param string|null $queue
+ * @return \Illuminate\Contracts\Queue\Job|null
+ */
+ public function pop($queue = null);
+
+ /**
+ * Get the connection name for the queue.
+ *
+ * @return string
+ */
+ public function getConnectionName();
+
+ /**
+ * Set the connection name for the queue.
+ *
+ * @param string $name
+ * @return $this
+ */
+ public function setConnectionName($name);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/QueueableCollection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/QueueableCollection.php
new file mode 100644
index 0000000..7f1ea19
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/QueueableCollection.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface QueueableCollection
+{
+ /**
+ * Get the type of the entities being queued.
+ *
+ * @return string|null
+ */
+ public function getQueueableClass();
+
+ /**
+ * Get the identifiers for all of the entities.
+ *
+ * @return array
+ */
+ public function getQueueableIds();
+
+ /**
+ * Get the relationships of the entities being queued.
+ *
+ * @return array
+ */
+ public function getQueueableRelations();
+
+ /**
+ * Get the connection of the entities being queued.
+ *
+ * @return string|null
+ */
+ public function getQueueableConnection();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/QueueableEntity.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/QueueableEntity.php
new file mode 100644
index 0000000..366f0c8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/QueueableEntity.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface QueueableEntity
+{
+ /**
+ * Get the queueable identity for the entity.
+ *
+ * @return mixed
+ */
+ public function getQueueableId();
+
+ /**
+ * Get the relationships for the entity.
+ *
+ * @return array
+ */
+ public function getQueueableRelations();
+
+ /**
+ * Get the connection of the entity.
+ *
+ * @return string|null
+ */
+ public function getQueueableConnection();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldBeEncrypted.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldBeEncrypted.php
new file mode 100644
index 0000000..374df89
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldBeEncrypted.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface ShouldBeEncrypted
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldBeUnique.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldBeUnique.php
new file mode 100644
index 0000000..b216434
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldBeUnique.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface ShouldBeUnique
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldBeUniqueUntilProcessing.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldBeUniqueUntilProcessing.php
new file mode 100644
index 0000000..510cab9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldBeUniqueUntilProcessing.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface ShouldBeUniqueUntilProcessing extends ShouldBeUnique
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldQueue.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldQueue.php
new file mode 100644
index 0000000..0e99652
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Queue/ShouldQueue.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Illuminate\Contracts\Queue;
+
+interface ShouldQueue
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/Connection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/Connection.php
new file mode 100644
index 0000000..74a8832
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/Connection.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Illuminate\Contracts\Redis;
+
+use Closure;
+
+interface Connection
+{
+ /**
+ * Subscribe to a set of given channels for messages.
+ *
+ * @param array|string $channels
+ * @param \Closure $callback
+ * @return void
+ */
+ public function subscribe($channels, Closure $callback);
+
+ /**
+ * Subscribe to a set of given channels with wildcards.
+ *
+ * @param array|string $channels
+ * @param \Closure $callback
+ * @return void
+ */
+ public function psubscribe($channels, Closure $callback);
+
+ /**
+ * Run a command against the Redis database.
+ *
+ * @param string $method
+ * @param array $parameters
+ * @return mixed
+ */
+ public function command($method, array $parameters = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/Connector.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/Connector.php
new file mode 100644
index 0000000..e2669f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/Connector.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Illuminate\Contracts\Redis;
+
+interface Connector
+{
+ /**
+ * Create a connection to a Redis cluster.
+ *
+ * @param array $config
+ * @param array $options
+ * @return \Illuminate\Redis\Connections\Connection
+ */
+ public function connect(array $config, array $options);
+
+ /**
+ * Create a connection to a Redis instance.
+ *
+ * @param array $config
+ * @param array $clusterOptions
+ * @param array $options
+ * @return \Illuminate\Redis\Connections\Connection
+ */
+ public function connectToCluster(array $config, array $clusterOptions, array $options);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/Factory.php
new file mode 100644
index 0000000..c2bfe81
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/Factory.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Redis;
+
+interface Factory
+{
+ /**
+ * Get a Redis connection by name.
+ *
+ * @param string|null $name
+ * @return \Illuminate\Redis\Connections\Connection
+ */
+ public function connection($name = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/LimiterTimeoutException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/LimiterTimeoutException.php
new file mode 100644
index 0000000..651bf90
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Redis/LimiterTimeoutException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Illuminate\Contracts\Redis;
+
+use Exception;
+
+class LimiterTimeoutException extends Exception
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/BindingRegistrar.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/BindingRegistrar.php
new file mode 100644
index 0000000..6ed5079
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/BindingRegistrar.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Illuminate\Contracts\Routing;
+
+interface BindingRegistrar
+{
+ /**
+ * Add a new route parameter binder.
+ *
+ * @param string $key
+ * @param string|callable $binder
+ * @return void
+ */
+ public function bind($key, $binder);
+
+ /**
+ * Get the binding callback for a given binding.
+ *
+ * @param string $key
+ * @return \Closure
+ */
+ public function getBindingCallback($key);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/Registrar.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/Registrar.php
new file mode 100644
index 0000000..57e3272
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/Registrar.php
@@ -0,0 +1,105 @@
+<?php
+
+namespace Illuminate\Contracts\Routing;
+
+interface Registrar
+{
+ /**
+ * Register a new GET route with the router.
+ *
+ * @param string $uri
+ * @param array|string|callable $action
+ * @return \Illuminate\Routing\Route
+ */
+ public function get($uri, $action);
+
+ /**
+ * Register a new POST route with the router.
+ *
+ * @param string $uri
+ * @param array|string|callable $action
+ * @return \Illuminate\Routing\Route
+ */
+ public function post($uri, $action);
+
+ /**
+ * Register a new PUT route with the router.
+ *
+ * @param string $uri
+ * @param array|string|callable $action
+ * @return \Illuminate\Routing\Route
+ */
+ public function put($uri, $action);
+
+ /**
+ * Register a new DELETE route with the router.
+ *
+ * @param string $uri
+ * @param array|string|callable $action
+ * @return \Illuminate\Routing\Route
+ */
+ public function delete($uri, $action);
+
+ /**
+ * Register a new PATCH route with the router.
+ *
+ * @param string $uri
+ * @param array|string|callable $action
+ * @return \Illuminate\Routing\Route
+ */
+ public function patch($uri, $action);
+
+ /**
+ * Register a new OPTIONS route with the router.
+ *
+ * @param string $uri
+ * @param array|string|callable $action
+ * @return \Illuminate\Routing\Route
+ */
+ public function options($uri, $action);
+
+ /**
+ * Register a new route with the given verbs.
+ *
+ * @param array|string $methods
+ * @param string $uri
+ * @param array|string|callable $action
+ * @return \Illuminate\Routing\Route
+ */
+ public function match($methods, $uri, $action);
+
+ /**
+ * Route a resource to a controller.
+ *
+ * @param string $name
+ * @param string $controller
+ * @param array $options
+ * @return \Illuminate\Routing\PendingResourceRegistration
+ */
+ public function resource($name, $controller, array $options = []);
+
+ /**
+ * Create a route group with shared attributes.
+ *
+ * @param array $attributes
+ * @param \Closure|string $routes
+ * @return void
+ */
+ public function group(array $attributes, $routes);
+
+ /**
+ * Substitute the route bindings onto the route.
+ *
+ * @param \Illuminate\Routing\Route $route
+ * @return \Illuminate\Routing\Route
+ */
+ public function substituteBindings($route);
+
+ /**
+ * Substitute the implicit Eloquent model bindings for the route.
+ *
+ * @param \Illuminate\Routing\Route $route
+ * @return void
+ */
+ public function substituteImplicitBindings($route);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/ResponseFactory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/ResponseFactory.php
new file mode 100644
index 0000000..2cd928d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/ResponseFactory.php
@@ -0,0 +1,155 @@
+<?php
+
+namespace Illuminate\Contracts\Routing;
+
+interface ResponseFactory
+{
+ /**
+ * Create a new response instance.
+ *
+ * @param string $content
+ * @param int $status
+ * @param array $headers
+ * @return \Illuminate\Http\Response
+ */
+ public function make($content = '', $status = 200, array $headers = []);
+
+ /**
+ * Create a new "no content" response.
+ *
+ * @param int $status
+ * @param array $headers
+ * @return \Illuminate\Http\Response
+ */
+ public function noContent($status = 204, array $headers = []);
+
+ /**
+ * Create a new response for a given view.
+ *
+ * @param string|array $view
+ * @param array $data
+ * @param int $status
+ * @param array $headers
+ * @return \Illuminate\Http\Response
+ */
+ public function view($view, $data = [], $status = 200, array $headers = []);
+
+ /**
+ * Create a new JSON response instance.
+ *
+ * @param mixed $data
+ * @param int $status
+ * @param array $headers
+ * @param int $options
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function json($data = [], $status = 200, array $headers = [], $options = 0);
+
+ /**
+ * Create a new JSONP response instance.
+ *
+ * @param string $callback
+ * @param mixed $data
+ * @param int $status
+ * @param array $headers
+ * @param int $options
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function jsonp($callback, $data = [], $status = 200, array $headers = [], $options = 0);
+
+ /**
+ * Create a new streamed response instance.
+ *
+ * @param \Closure $callback
+ * @param int $status
+ * @param array $headers
+ * @return \Symfony\Component\HttpFoundation\StreamedResponse
+ */
+ public function stream($callback, $status = 200, array $headers = []);
+
+ /**
+ * Create a new streamed response instance as a file download.
+ *
+ * @param \Closure $callback
+ * @param string|null $name
+ * @param array $headers
+ * @param string|null $disposition
+ * @return \Symfony\Component\HttpFoundation\StreamedResponse
+ */
+ public function streamDownload($callback, $name = null, array $headers = [], $disposition = 'attachment');
+
+ /**
+ * Create a new file download response.
+ *
+ * @param \SplFileInfo|string $file
+ * @param string|null $name
+ * @param array $headers
+ * @param string|null $disposition
+ * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
+ */
+ public function download($file, $name = null, array $headers = [], $disposition = 'attachment');
+
+ /**
+ * Return the raw contents of a binary file.
+ *
+ * @param \SplFileInfo|string $file
+ * @param array $headers
+ * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
+ */
+ public function file($file, array $headers = []);
+
+ /**
+ * Create a new redirect response to the given path.
+ *
+ * @param string $path
+ * @param int $status
+ * @param array $headers
+ * @param bool|null $secure
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function redirectTo($path, $status = 302, $headers = [], $secure = null);
+
+ /**
+ * Create a new redirect response to a named route.
+ *
+ * @param string $route
+ * @param mixed $parameters
+ * @param int $status
+ * @param array $headers
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function redirectToRoute($route, $parameters = [], $status = 302, $headers = []);
+
+ /**
+ * Create a new redirect response to a controller action.
+ *
+ * @param string $action
+ * @param mixed $parameters
+ * @param int $status
+ * @param array $headers
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function redirectToAction($action, $parameters = [], $status = 302, $headers = []);
+
+ /**
+ * Create a new redirect response, while putting the current URL in the session.
+ *
+ * @param string $path
+ * @param int $status
+ * @param array $headers
+ * @param bool|null $secure
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function redirectGuest($path, $status = 302, $headers = [], $secure = null);
+
+ /**
+ * Create a new redirect response to the previously intended location.
+ *
+ * @param string $default
+ * @param int $status
+ * @param array $headers
+ * @param bool|null $secure
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function redirectToIntended($default = '/', $status = 302, $headers = [], $secure = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/UrlGenerator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/UrlGenerator.php
new file mode 100644
index 0000000..e576dda
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/UrlGenerator.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Illuminate\Contracts\Routing;
+
+interface UrlGenerator
+{
+ /**
+ * Get the current URL for the request.
+ *
+ * @return string
+ */
+ public function current();
+
+ /**
+ * Get the URL for the previous request.
+ *
+ * @param mixed $fallback
+ * @return string
+ */
+ public function previous($fallback = false);
+
+ /**
+ * Generate an absolute URL to the given path.
+ *
+ * @param string $path
+ * @param mixed $extra
+ * @param bool|null $secure
+ * @return string
+ */
+ public function to($path, $extra = [], $secure = null);
+
+ /**
+ * Generate a secure, absolute URL to the given path.
+ *
+ * @param string $path
+ * @param array $parameters
+ * @return string
+ */
+ public function secure($path, $parameters = []);
+
+ /**
+ * Generate the URL to an application asset.
+ *
+ * @param string $path
+ * @param bool|null $secure
+ * @return string
+ */
+ public function asset($path, $secure = null);
+
+ /**
+ * Get the URL to a named route.
+ *
+ * @param string $name
+ * @param mixed $parameters
+ * @param bool $absolute
+ * @return string
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function route($name, $parameters = [], $absolute = true);
+
+ /**
+ * Get the URL to a controller action.
+ *
+ * @param string|array $action
+ * @param mixed $parameters
+ * @param bool $absolute
+ * @return string
+ */
+ public function action($action, $parameters = [], $absolute = true);
+
+ /**
+ * Set the root controller namespace.
+ *
+ * @param string $rootNamespace
+ * @return $this
+ */
+ public function setRootControllerNamespace($rootNamespace);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/UrlRoutable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/UrlRoutable.php
new file mode 100644
index 0000000..48c3d72
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Routing/UrlRoutable.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Illuminate\Contracts\Routing;
+
+interface UrlRoutable
+{
+ /**
+ * Get the value of the model's route key.
+ *
+ * @return mixed
+ */
+ public function getRouteKey();
+
+ /**
+ * Get the route key for the model.
+ *
+ * @return string
+ */
+ public function getRouteKeyName();
+
+ /**
+ * Retrieve the model for a bound value.
+ *
+ * @param mixed $value
+ * @param string|null $field
+ * @return \Illuminate\Database\Eloquent\Model|null
+ */
+ public function resolveRouteBinding($value, $field = null);
+
+ /**
+ * Retrieve the child model for a bound value.
+ *
+ * @param string $childType
+ * @param mixed $value
+ * @param string|null $field
+ * @return \Illuminate\Database\Eloquent\Model|null
+ */
+ public function resolveChildRouteBinding($childType, $value, $field);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Session/Session.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Session/Session.php
new file mode 100644
index 0000000..1bf025a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Session/Session.php
@@ -0,0 +1,204 @@
+<?php
+
+namespace Illuminate\Contracts\Session;
+
+interface Session
+{
+ /**
+ * Get the name of the session.
+ *
+ * @return string
+ */
+ public function getName();
+
+ /**
+ * Set the name of the session.
+ *
+ * @param string $name
+ * @return void
+ */
+ public function setName($name);
+
+ /**
+ * Get the current session ID.
+ *
+ * @return string
+ */
+ public function getId();
+
+ /**
+ * Set the session ID.
+ *
+ * @param string $id
+ * @return void
+ */
+ public function setId($id);
+
+ /**
+ * Start the session, reading the data from a handler.
+ *
+ * @return bool
+ */
+ public function start();
+
+ /**
+ * Save the session data to storage.
+ *
+ * @return void
+ */
+ public function save();
+
+ /**
+ * Get all of the session data.
+ *
+ * @return array
+ */
+ public function all();
+
+ /**
+ * Checks if a key exists.
+ *
+ * @param string|array $key
+ * @return bool
+ */
+ public function exists($key);
+
+ /**
+ * Checks if a key is present and not null.
+ *
+ * @param string|array $key
+ * @return bool
+ */
+ public function has($key);
+
+ /**
+ * Get an item from the session.
+ *
+ * @param string $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public function get($key, $default = null);
+
+ /**
+ * Get the value of a given key and then forget it.
+ *
+ * @param string $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public function pull($key, $default = null);
+
+ /**
+ * Put a key / value pair or array of key / value pairs in the session.
+ *
+ * @param string|array $key
+ * @param mixed $value
+ * @return void
+ */
+ public function put($key, $value = null);
+
+ /**
+ * Get the CSRF token value.
+ *
+ * @return string
+ */
+ public function token();
+
+ /**
+ * Regenerate the CSRF token value.
+ *
+ * @return void
+ */
+ public function regenerateToken();
+
+ /**
+ * Remove an item from the session, returning its value.
+ *
+ * @param string $key
+ * @return mixed
+ */
+ public function remove($key);
+
+ /**
+ * Remove one or many items from the session.
+ *
+ * @param string|array $keys
+ * @return void
+ */
+ public function forget($keys);
+
+ /**
+ * Remove all of the items from the session.
+ *
+ * @return void
+ */
+ public function flush();
+
+ /**
+ * Flush the session data and regenerate the ID.
+ *
+ * @return bool
+ */
+ public function invalidate();
+
+ /**
+ * Generate a new session identifier.
+ *
+ * @param bool $destroy
+ * @return bool
+ */
+ public function regenerate($destroy = false);
+
+ /**
+ * Generate a new session ID for the session.
+ *
+ * @param bool $destroy
+ * @return bool
+ */
+ public function migrate($destroy = false);
+
+ /**
+ * Determine if the session has been started.
+ *
+ * @return bool
+ */
+ public function isStarted();
+
+ /**
+ * Get the previous URL from the session.
+ *
+ * @return string|null
+ */
+ public function previousUrl();
+
+ /**
+ * Set the "previous" URL in the session.
+ *
+ * @param string $url
+ * @return void
+ */
+ public function setPreviousUrl($url);
+
+ /**
+ * Get the session handler instance.
+ *
+ * @return \SessionHandlerInterface
+ */
+ public function getHandler();
+
+ /**
+ * Determine if the session handler needs a request.
+ *
+ * @return bool
+ */
+ public function handlerNeedsRequest();
+
+ /**
+ * Set the request on the handler instance.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @return void
+ */
+ public function setRequestOnHandler($request);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Arrayable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Arrayable.php
new file mode 100755
index 0000000..5ad93b7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Arrayable.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Illuminate\Contracts\Support;
+
+interface Arrayable
+{
+ /**
+ * Get the instance as an array.
+ *
+ * @return array
+ */
+ public function toArray();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/DeferrableProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/DeferrableProvider.php
new file mode 100644
index 0000000..cfecf8b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/DeferrableProvider.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Illuminate\Contracts\Support;
+
+interface DeferrableProvider
+{
+ /**
+ * Get the services provided by the provider.
+ *
+ * @return array
+ */
+ public function provides();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/DeferringDisplayableValue.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/DeferringDisplayableValue.php
new file mode 100644
index 0000000..ac21d7e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/DeferringDisplayableValue.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Illuminate\Contracts\Support;
+
+interface DeferringDisplayableValue
+{
+ /**
+ * Resolve the displayable value that the class is deferring.
+ *
+ * @return \Illuminate\Contracts\Support\Htmlable|string
+ */
+ public function resolveDisplayableValue();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Htmlable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Htmlable.php
new file mode 100644
index 0000000..32f643a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Htmlable.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Illuminate\Contracts\Support;
+
+interface Htmlable
+{
+ /**
+ * Get content as a string of HTML.
+ *
+ * @return string
+ */
+ public function toHtml();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Jsonable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Jsonable.php
new file mode 100755
index 0000000..f5641c3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Jsonable.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Support;
+
+interface Jsonable
+{
+ /**
+ * Convert the object to its JSON representation.
+ *
+ * @param int $options
+ * @return string
+ */
+ public function toJson($options = 0);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/MessageBag.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/MessageBag.php
new file mode 100644
index 0000000..7f708ac
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/MessageBag.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace Illuminate\Contracts\Support;
+
+use Countable;
+
+interface MessageBag extends Arrayable, Countable
+{
+ /**
+ * Get the keys present in the message bag.
+ *
+ * @return array
+ */
+ public function keys();
+
+ /**
+ * Add a message to the bag.
+ *
+ * @param string $key
+ * @param string $message
+ * @return $this
+ */
+ public function add($key, $message);
+
+ /**
+ * Merge a new array of messages into the bag.
+ *
+ * @param \Illuminate\Contracts\Support\MessageProvider|array $messages
+ * @return $this
+ */
+ public function merge($messages);
+
+ /**
+ * Determine if messages exist for a given key.
+ *
+ * @param string|array $key
+ * @return bool
+ */
+ public function has($key);
+
+ /**
+ * Get the first message from the bag for a given key.
+ *
+ * @param string|null $key
+ * @param string|null $format
+ * @return string
+ */
+ public function first($key = null, $format = null);
+
+ /**
+ * Get all of the messages from the bag for a given key.
+ *
+ * @param string $key
+ * @param string|null $format
+ * @return array
+ */
+ public function get($key, $format = null);
+
+ /**
+ * Get all of the messages for every key in the bag.
+ *
+ * @param string|null $format
+ * @return array
+ */
+ public function all($format = null);
+
+ /**
+ * Get the raw messages in the container.
+ *
+ * @return array
+ */
+ public function getMessages();
+
+ /**
+ * Get the default message format.
+ *
+ * @return string
+ */
+ public function getFormat();
+
+ /**
+ * Set the default message format.
+ *
+ * @param string $format
+ * @return $this
+ */
+ public function setFormat($format = ':message');
+
+ /**
+ * Determine if the message bag has any messages.
+ *
+ * @return bool
+ */
+ public function isEmpty();
+
+ /**
+ * Determine if the message bag has any messages.
+ *
+ * @return bool
+ */
+ public function isNotEmpty();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/MessageProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/MessageProvider.php
new file mode 100755
index 0000000..f15ce73
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/MessageProvider.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Illuminate\Contracts\Support;
+
+interface MessageProvider
+{
+ /**
+ * Get the messages for the instance.
+ *
+ * @return \Illuminate\Contracts\Support\MessageBag
+ */
+ public function getMessageBag();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Renderable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Renderable.php
new file mode 100755
index 0000000..25c181e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Renderable.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Illuminate\Contracts\Support;
+
+interface Renderable
+{
+ /**
+ * Get the evaluated contents of the object.
+ *
+ * @return string
+ */
+ public function render();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Responsable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Responsable.php
new file mode 100644
index 0000000..1738ec0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Support/Responsable.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Support;
+
+interface Responsable
+{
+ /**
+ * Create an HTTP response that represents the object.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @return \Symfony\Component\HttpFoundation\Response
+ */
+ public function toResponse($request);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Translation/HasLocalePreference.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Translation/HasLocalePreference.php
new file mode 100644
index 0000000..1b1f16d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Translation/HasLocalePreference.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Illuminate\Contracts\Translation;
+
+interface HasLocalePreference
+{
+ /**
+ * Get the preferred locale of the entity.
+ *
+ * @return string|null
+ */
+ public function preferredLocale();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Translation/Loader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Translation/Loader.php
new file mode 100755
index 0000000..b08418d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Translation/Loader.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Illuminate\Contracts\Translation;
+
+interface Loader
+{
+ /**
+ * Load the messages for the given locale.
+ *
+ * @param string $locale
+ * @param string $group
+ * @param string|null $namespace
+ * @return array
+ */
+ public function load($locale, $group, $namespace = null);
+
+ /**
+ * Add a new namespace to the loader.
+ *
+ * @param string $namespace
+ * @param string $hint
+ * @return void
+ */
+ public function addNamespace($namespace, $hint);
+
+ /**
+ * Add a new JSON path to the loader.
+ *
+ * @param string $path
+ * @return void
+ */
+ public function addJsonPath($path);
+
+ /**
+ * Get an array of all the registered namespaces.
+ *
+ * @return array
+ */
+ public function namespaces();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Translation/Translator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Translation/Translator.php
new file mode 100644
index 0000000..6eae491
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Translation/Translator.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace Illuminate\Contracts\Translation;
+
+interface Translator
+{
+ /**
+ * Get the translation for a given key.
+ *
+ * @param string $key
+ * @param array $replace
+ * @param string|null $locale
+ * @return mixed
+ */
+ public function get($key, array $replace = [], $locale = null);
+
+ /**
+ * Get a translation according to an integer value.
+ *
+ * @param string $key
+ * @param \Countable|int|array $number
+ * @param array $replace
+ * @param string|null $locale
+ * @return string
+ */
+ public function choice($key, $number, array $replace = [], $locale = null);
+
+ /**
+ * Get the default locale being used.
+ *
+ * @return string
+ */
+ public function getLocale();
+
+ /**
+ * Set the default locale.
+ *
+ * @param string $locale
+ * @return void
+ */
+ public function setLocale($locale);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/DataAwareRule.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/DataAwareRule.php
new file mode 100644
index 0000000..7ec7ab5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/DataAwareRule.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Validation;
+
+interface DataAwareRule
+{
+ /**
+ * Set the data under validation.
+ *
+ * @param array $data
+ * @return $this
+ */
+ public function setData($data);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/Factory.php
new file mode 100644
index 0000000..104675a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/Factory.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace Illuminate\Contracts\Validation;
+
+interface Factory
+{
+ /**
+ * Create a new Validator instance.
+ *
+ * @param array $data
+ * @param array $rules
+ * @param array $messages
+ * @param array $customAttributes
+ * @return \Illuminate\Contracts\Validation\Validator
+ */
+ public function make(array $data, array $rules, array $messages = [], array $customAttributes = []);
+
+ /**
+ * Register a custom validator extension.
+ *
+ * @param string $rule
+ * @param \Closure|string $extension
+ * @param string|null $message
+ * @return void
+ */
+ public function extend($rule, $extension, $message = null);
+
+ /**
+ * Register a custom implicit validator extension.
+ *
+ * @param string $rule
+ * @param \Closure|string $extension
+ * @param string|null $message
+ * @return void
+ */
+ public function extendImplicit($rule, $extension, $message = null);
+
+ /**
+ * Register a custom implicit validator message replacer.
+ *
+ * @param string $rule
+ * @param \Closure|string $replacer
+ * @return void
+ */
+ public function replacer($rule, $replacer);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/ImplicitRule.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/ImplicitRule.php
new file mode 100644
index 0000000..bbc64f4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/ImplicitRule.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Illuminate\Contracts\Validation;
+
+interface ImplicitRule extends Rule
+{
+ //
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/Rule.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/Rule.php
new file mode 100644
index 0000000..cc03777
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/Rule.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Illuminate\Contracts\Validation;
+
+interface Rule
+{
+ /**
+ * Determine if the validation rule passes.
+ *
+ * @param string $attribute
+ * @param mixed $value
+ * @return bool
+ */
+ public function passes($attribute, $value);
+
+ /**
+ * Get the validation error message.
+ *
+ * @return string|array
+ */
+ public function message();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/UncompromisedVerifier.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/UncompromisedVerifier.php
new file mode 100644
index 0000000..d4bd597
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/UncompromisedVerifier.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Validation;
+
+interface UncompromisedVerifier
+{
+ /**
+ * Verify that the given data has not been compromised in data leaks.
+ *
+ * @param array $data
+ * @return bool
+ */
+ public function verify($data);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/ValidatesWhenResolved.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/ValidatesWhenResolved.php
new file mode 100644
index 0000000..4e6b757
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/ValidatesWhenResolved.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Illuminate\Contracts\Validation;
+
+interface ValidatesWhenResolved
+{
+ /**
+ * Validate the given class instance.
+ *
+ * @return void
+ */
+ public function validateResolved();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/Validator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/Validator.php
new file mode 100644
index 0000000..f68498d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/Validator.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Illuminate\Contracts\Validation;
+
+use Illuminate\Contracts\Support\MessageProvider;
+
+interface Validator extends MessageProvider
+{
+ /**
+ * Run the validator's rules against its data.
+ *
+ * @return array
+ *
+ * @throws \Illuminate\Validation\ValidationException
+ */
+ public function validate();
+
+ /**
+ * Get the attributes and values that were validated.
+ *
+ * @return array
+ *
+ * @throws \Illuminate\Validation\ValidationException
+ */
+ public function validated();
+
+ /**
+ * Determine if the data fails the validation rules.
+ *
+ * @return bool
+ */
+ public function fails();
+
+ /**
+ * Get the failed validation rules.
+ *
+ * @return array
+ */
+ public function failed();
+
+ /**
+ * Add conditions to a given field based on a Closure.
+ *
+ * @param string|array $attribute
+ * @param string|array $rules
+ * @param callable $callback
+ * @return $this
+ */
+ public function sometimes($attribute, $rules, callable $callback);
+
+ /**
+ * Add an after validation callback.
+ *
+ * @param callable|string $callback
+ * @return $this
+ */
+ public function after($callback);
+
+ /**
+ * Get all of the validation error messages.
+ *
+ * @return \Illuminate\Support\MessageBag
+ */
+ public function errors();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/ValidatorAwareRule.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/ValidatorAwareRule.php
new file mode 100644
index 0000000..053f4fa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/Validation/ValidatorAwareRule.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Illuminate\Contracts\Validation;
+
+interface ValidatorAwareRule
+{
+ /**
+ * Set the current validator.
+ *
+ * @param \Illuminate\Validation\Validator $validator
+ * @return $this
+ */
+ public function setValidator($validator);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/View/Engine.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/View/Engine.php
new file mode 100755
index 0000000..be4795d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/View/Engine.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Illuminate\Contracts\View;
+
+interface Engine
+{
+ /**
+ * Get the evaluated contents of the view.
+ *
+ * @param string $path
+ * @param array $data
+ * @return string
+ */
+ public function get($path, array $data = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/View/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/View/Factory.php
new file mode 100644
index 0000000..562ee79
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/View/Factory.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Illuminate\Contracts\View;
+
+interface Factory
+{
+ /**
+ * Determine if a given view exists.
+ *
+ * @param string $view
+ * @return bool
+ */
+ public function exists($view);
+
+ /**
+ * Get the evaluated view contents for the given path.
+ *
+ * @param string $path
+ * @param \Illuminate\Contracts\Support\Arrayable|array $data
+ * @param array $mergeData
+ * @return \Illuminate\Contracts\View\View
+ */
+ public function file($path, $data = [], $mergeData = []);
+
+ /**
+ * Get the evaluated view contents for the given view.
+ *
+ * @param string $view
+ * @param \Illuminate\Contracts\Support\Arrayable|array $data
+ * @param array $mergeData
+ * @return \Illuminate\Contracts\View\View
+ */
+ public function make($view, $data = [], $mergeData = []);
+
+ /**
+ * Add a piece of shared data to the environment.
+ *
+ * @param array|string $key
+ * @param mixed $value
+ * @return mixed
+ */
+ public function share($key, $value = null);
+
+ /**
+ * Register a view composer event.
+ *
+ * @param array|string $views
+ * @param \Closure|string $callback
+ * @return array
+ */
+ public function composer($views, $callback);
+
+ /**
+ * Register a view creator event.
+ *
+ * @param array|string $views
+ * @param \Closure|string $callback
+ * @return array
+ */
+ public function creator($views, $callback);
+
+ /**
+ * Add a new namespace to the loader.
+ *
+ * @param string $namespace
+ * @param string|array $hints
+ * @return $this
+ */
+ public function addNamespace($namespace, $hints);
+
+ /**
+ * Replace the namespace hints for the given namespace.
+ *
+ * @param string $namespace
+ * @param string|array $hints
+ * @return $this
+ */
+ public function replaceNamespace($namespace, $hints);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/View/View.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/View/View.php
new file mode 100644
index 0000000..4b0b7f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/View/View.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Illuminate\Contracts\View;
+
+use Illuminate\Contracts\Support\Renderable;
+
+interface View extends Renderable
+{
+ /**
+ * Get the name of the view.
+ *
+ * @return string
+ */
+ public function name();
+
+ /**
+ * Add a piece of data to the view.
+ *
+ * @param string|array $key
+ * @param mixed $value
+ * @return $this
+ */
+ public function with($key, $value = null);
+
+ /**
+ * Get the array of view data.
+ *
+ * @return array
+ */
+ public function getData();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/composer.json
new file mode 100644
index 0000000..c9b4667
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/illuminate/contracts/composer.json
@@ -0,0 +1,35 @@
+{
+ "name": "illuminate/contracts",
+ "description": "The Illuminate Contracts package.",
+ "license": "MIT",
+ "homepage": "https://laravel.com",
+ "support": {
+ "issues": "https://github.com/laravel/framework/issues",
+ "source": "https://github.com/laravel/framework"
+ },
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ }
+ ],
+ "require": {
+ "php": "^7.3|^8.0",
+ "psr/container": "^1.0",
+ "psr/simple-cache": "^1.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Illuminate\\Contracts\\": ""
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "8.x-dev"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "minimum-stability": "dev"
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/Dockerfile b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/Dockerfile
index fc36a81..5917e05 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/Dockerfile
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/Dockerfile
@@ -5,8 +5,8 @@
WORKDIR /var/www
RUN apt-get update
-RUN apt-get install -y zip unzip zlib1g-dev
-RUN if [[ `php-config --vernum` -ge 73000 ]]; then docker-php-ext-install zip; fi
+RUN apt-get install -y zip unzip libzip-dev git
+RUN docker-php-ext-install zip
RUN docker-php-ext-install pcntl
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/composer.json
index 6d81b4f..a6dd4ab 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/composer.json
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/composer.json
@@ -19,8 +19,8 @@
"matthiasmullie/path-converter": "~1.1"
},
"require-dev": {
- "matthiasmullie/scrapbook": "~1.0",
- "phpunit/phpunit": "~4.8",
+ "matthiasmullie/scrapbook": "dev-master",
+ "phpunit/phpunit": ">=4.8",
"friendsofphp/php-cs-fixer": "~2.0"
},
"suggest": {
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/CSS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/CSS.php
index ea8e8cd..eb98e52 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/CSS.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/CSS.php
@@ -685,7 +685,7 @@
protected function extractMath()
{
$functions = array('calc', 'clamp', 'min', 'max');
- $pattern = '/('. implode('|', $functions) .')(\(.+?)(?=$|;|})/m';
+ $pattern = '/\b('. implode('|', $functions) .')(\(.+?)(?=$|;|})/m';
// PHP only supports $this inside anonymous functions since 5.4
$minifier = $this;
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/JS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/JS.php
index 92389cd..a0fa649 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/JS.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/JS.php
@@ -254,7 +254,7 @@
// of the RegExp methods (a `\` followed by a variable or value is
// likely part of a division, not a regex)
$keywords = array('do', 'in', 'new', 'else', 'throw', 'yield', 'delete', 'return', 'typeof');
- $before = '([=:,;\+\-\*\/\}\(\{\[&\|!]|^|'.implode('|', $keywords).')\s*';
+ $before = '(^|[=:,;\+\-\*\/\}\(\{\[&\|!]|'.implode('|', $keywords).')\s*';
$propertiesAndMethods = array(
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Properties_2
'constructor',
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/Minify.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/Minify.php
index 3f40bc1..4d8dcf4 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/Minify.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/matthiasmullie/minify/src/Minify.php
@@ -105,7 +105,7 @@
* @param string|string[] $data
*
* @return static
- *
+ *
* @throws IOException
*/
public function addFile($data /* $data = null, ... */)
@@ -472,7 +472,7 @@
*/
protected function openFileForWriting($path)
{
- if (($handler = @fopen($path, 'w')) === false) {
+ if ($path === '' || ($handler = @fopen($path, 'w')) === false) {
throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.');
}
@@ -490,7 +490,11 @@
*/
protected function writeToFile($handler, $content, $path = '')
{
- if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) {
+ if (
+ !is_resource($handler) ||
+ ($result = @fwrite($handler, $content)) === false ||
+ ($result < strlen($content))
+ ) {
throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.');
}
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/LICENSE
new file mode 100644
index 0000000..6de45eb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) Brian Nesbitt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/bin/carbon b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/bin/carbon
new file mode 100755
index 0000000..fdcbb5c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/bin/carbon
@@ -0,0 +1,21 @@
+#!/usr/bin/env php
+<?php
+
+$dir = __DIR__.'/..';
+
+if (!file_exists($dir.'/autoload.php')) {
+ $dir = __DIR__.'/../vendor';
+}
+
+if (!file_exists($dir.'/autoload.php')) {
+ $dir = __DIR__.'/../../..';
+}
+
+if (!file_exists($dir.'/autoload.php')) {
+ echo 'Autoload not found.';
+ exit(1);
+}
+
+require $dir.'/autoload.php';
+
+exit((new \Carbon\Cli\Invoker())(...$argv) ? 0 : 1);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/bin/carbon.bat b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/bin/carbon.bat
new file mode 100644
index 0000000..84599d3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/bin/carbon.bat
@@ -0,0 +1,4 @@
+@ECHO OFF
+setlocal DISABLEDELAYEDEXPANSION
+SET BIN_TARGET=%~dp0/carbon
+php "%BIN_TARGET%" %*
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/composer.json
new file mode 100644
index 0000000..d0cadc9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/composer.json
@@ -0,0 +1,98 @@
+{
+ "name": "nesbot/carbon",
+ "type": "library",
+ "description": "An API extension for DateTime that supports 281 different languages.",
+ "keywords": [
+ "date",
+ "time",
+ "DateTime"
+ ],
+ "homepage": "https://carbon.nesbot.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Brian Nesbitt",
+ "email": "brian@nesbot.com",
+ "homepage": "https://markido.com"
+ },
+ {
+ "name": "kylekatarnls",
+ "homepage": "https://github.com/kylekatarnls"
+ }
+ ],
+ "require": {
+ "php": "^7.1.8 || ^8.0",
+ "ext-json": "*",
+ "symfony/polyfill-mbstring": "^1.0",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/translation": "^3.4 || ^4.0 || ^5.0"
+ },
+ "require-dev": {
+ "doctrine/orm": "^2.7",
+ "friendsofphp/php-cs-fixer": "^2.14 || ^3.0",
+ "kylekatarnls/multi-tester": "^2.0",
+ "phpmd/phpmd": "^2.9",
+ "phpstan/extension-installer": "^1.0",
+ "phpstan/phpstan": "^0.12.54",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.14",
+ "squizlabs/php_codesniffer": "^3.4"
+ },
+ "config": {
+ "process-timeout": 0,
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-3.x": "3.x-dev",
+ "dev-master": "2.x-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Carbon\\Laravel\\ServiceProvider"
+ ]
+ },
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Carbon\\": "src/Carbon/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Tests\\": "tests/"
+ },
+ "files": [
+ "tests/Laravel/ServiceProvider.php"
+ ]
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true,
+ "bin": [
+ "bin/carbon"
+ ],
+ "scripts": {
+ "phpcs": "php-cs-fixer fix -v --diff --dry-run",
+ "phpdoc": "php phpdoc.php",
+ "phpmd": "phpmd src text /phpmd.xml",
+ "phpstan": "phpstan analyse --configuration phpstan.neon",
+ "phpunit": "phpunit --verbose",
+ "style-check": [
+ "@phpcs",
+ "@phpstan",
+ "@phpmd"
+ ],
+ "test": [
+ "@phpunit",
+ "@style-check"
+ ]
+ },
+ "support": {
+ "issues": "https://github.com/briannesbitt/Carbon/issues",
+ "source": "https://github.com/briannesbitt/Carbon"
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/extension.neon b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/extension.neon
new file mode 100644
index 0000000..33bf794
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/extension.neon
@@ -0,0 +1,5 @@
+services:
+ -
+ class: Carbon\PHPStan\MacroExtension
+ tags:
+ - phpstan.broker.methodsClassReflectionExtension
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/readme.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/readme.md
new file mode 100644
index 0000000..70279c1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/readme.md
@@ -0,0 +1,146 @@
+# Carbon
+
+[![Latest Stable Version](https://img.shields.io/packagist/v/nesbot/carbon.svg?style=flat-square)](https://packagist.org/packages/nesbot/carbon)
+[![Total Downloads](https://img.shields.io/packagist/dt/nesbot/carbon.svg?style=flat-square)](https://packagist.org/packages/nesbot/carbon)
+[![GitHub Actions](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fbriannesbitt%2FCarbon%2Fbadge&style=flat-square&label=Build&logo=none)](https://actions-badge.atrox.dev/briannesbitt/Carbon/goto)
+[![StyleCI](https://github.styleci.io/repos/5724990/shield?style=flat-square)](https://github.styleci.io/repos/5724990)
+[![codecov.io](https://img.shields.io/codecov/c/github/briannesbitt/Carbon.svg?style=flat-square)](https://codecov.io/github/briannesbitt/Carbon?branch=master)
+[![PHPStan](https://img.shields.io/badge/PHPStan-enabled-44CC11.svg?longCache=true&style=flat-square)](https://github.com/phpstan/phpstan)
+[![Tidelift](https://tidelift.com/badges/github/briannesbitt/Carbon)](https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme)
+
+An international PHP extension for DateTime. [https://carbon.nesbot.com](https://carbon.nesbot.com)
+
+```php
+<?php
+
+use Carbon\Carbon;
+
+printf("Right now is %s", Carbon::now()->toDateTimeString());
+printf("Right now in Vancouver is %s", Carbon::now('America/Vancouver')); //implicit __toString()
+$tomorrow = Carbon::now()->addDay();
+$lastWeek = Carbon::now()->subWeek();
+$nextSummerOlympics = Carbon::createFromDate(2016)->addYears(4);
+
+$officialDate = Carbon::now()->toRfc2822String();
+
+$howOldAmI = Carbon::createFromDate(1975, 5, 21)->age;
+
+$noonTodayLondonTime = Carbon::createFromTime(12, 0, 0, 'Europe/London');
+
+$internetWillBlowUpOn = Carbon::create(2038, 01, 19, 3, 14, 7, 'GMT');
+
+// Don't really want this to happen so mock now
+Carbon::setTestNow(Carbon::createFromDate(2000, 1, 1));
+
+// comparisons are always done in UTC
+if (Carbon::now()->gte($internetWillBlowUpOn)) {
+ die();
+}
+
+// Phew! Return to normal behaviour
+Carbon::setTestNow();
+
+if (Carbon::now()->isWeekend()) {
+ echo 'Party!';
+}
+// Over 200 languages (and over 500 regional variants) supported:
+echo Carbon::now()->subMinutes(2)->diffForHumans(); // '2 minutes ago'
+echo Carbon::now()->subMinutes(2)->locale('zh_CN')->diffForHumans(); // '2分钟前'
+echo Carbon::parse('2019-07-23 14:51')->isoFormat('LLLL'); // 'Tuesday, July 23, 2019 2:51 PM'
+echo Carbon::parse('2019-07-23 14:51')->locale('fr_FR')->isoFormat('LLLL'); // 'mardi 23 juillet 2019 14:51'
+
+// ... but also does 'from now', 'after' and 'before'
+// rolling up to seconds, minutes, hours, days, months, years
+
+$daysSinceEpoch = Carbon::createFromTimestamp(0)->diffInDays();
+```
+
+[Get supported nesbot/carbon with the Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme)
+
+## Installation
+
+### With Composer
+
+```
+$ composer require nesbot/carbon
+```
+
+```json
+{
+ "require": {
+ "nesbot/carbon": "^2.16"
+ }
+}
+```
+
+```php
+<?php
+require 'vendor/autoload.php';
+
+use Carbon\Carbon;
+
+printf("Now: %s", Carbon::now());
+```
+
+### Without Composer
+
+Why are you not using [composer](https://getcomposer.org/)? Download the Carbon [latest release](https://github.com/briannesbitt/Carbon/releases) and put the contents of the ZIP archive into a directory in your project. Then require the file `autoload.php` to get all classes and dependencies loaded on need.
+
+```php
+<?php
+require 'path-to-Carbon-directory/autoload.php';
+
+use Carbon\Carbon;
+
+printf("Now: %s", Carbon::now());
+```
+
+## Docs
+
+[https://carbon.nesbot.com/docs](https://carbon.nesbot.com/docs)
+
+## Security contact information
+
+To report a security vulnerability, please use the
+[Tidelift security contact](https://tidelift.com/security).
+Tidelift will coordinate the fix and disclosure.
+
+## Credits
+
+### Contributors
+
+This project exists thanks to all the people who contribute.
+
+<a href="https://github.com/briannesbitt/Carbon/graphs/contributors" target="_blank"><img src="https://opencollective.com/Carbon/contributors.svg?width=890&button=false" /></a>
+
+### Translators
+
+[Thanks to people helping us to translate Carbon in so many languages](https://carbon.nesbot.com/contribute/translators/)
+
+### Sponsors
+
+Support this project by becoming a sponsor. Your logo will show up here with a link to your website.
+
+<a href="https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme" target="_blank"><img src="https://carbon.nesbot.com/tidelift-brand.png" width="256" height="64"></a>
+<a href="https://onlinecasinohex.ca/?utm_source=opencollective&utm_medium=github&utm_campaign=Carbon" target="_blank"><img src="https://images.opencollective.com/hexcasinoca/2da3af2/logo/256.png" width="85" height="64"></a>
+<a href="https://opencollective.com/Carbon/sponsor/0/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/0/avatar.svg"></a>
+<a href="https://opencollective.com/Carbon/sponsor/1/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/Carbon/sponsor/2/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/2/avatar.svg"></a>
+<a href="https://opencollective.com/Carbon/sponsor/3/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/3/avatar.svg"></a>
+<a href="https://opencollective.com/Carbon/sponsor/4/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/4/avatar.svg"></a>
+
+[[Become a sponsor](https://opencollective.com/Carbon#sponsor)]
+
+### Backers
+
+Thank you to all our backers! 🙏
+
+<a href="https://opencollective.com/Carbon#backers" target="_blank"><img src="https://opencollective.com/Carbon/backers.svg?width=890"></a>
+
+[[Become a backer](https://opencollective.com/Carbon#backer)]
+
+## Carbon for enterprise
+
+Available as part of the Tidelift Subscription.
+
+The maintainers of ``Carbon`` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Carbon.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Carbon.php
new file mode 100644
index 0000000..3b68759
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Carbon.php
@@ -0,0 +1,523 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use Carbon\Traits\Date;
+use DateTime;
+use DateTimeInterface;
+use DateTimeZone;
+
+/**
+ * A simple API extension for DateTime.
+ *
+ * <autodoc generated by `composer phpdoc`>
+ *
+ * @property int $year
+ * @property int $yearIso
+ * @property int $month
+ * @property int $day
+ * @property int $hour
+ * @property int $minute
+ * @property int $second
+ * @property int $micro
+ * @property int $microsecond
+ * @property int|float|string $timestamp seconds since the Unix Epoch
+ * @property string $englishDayOfWeek the day of week in English
+ * @property string $shortEnglishDayOfWeek the abbreviated day of week in English
+ * @property string $englishMonth the month in English
+ * @property string $shortEnglishMonth the abbreviated month in English
+ * @property string $localeDayOfWeek the day of week in current locale LC_TIME
+ * @property string $shortLocaleDayOfWeek the abbreviated day of week in current locale LC_TIME
+ * @property string $localeMonth the month in current locale LC_TIME
+ * @property string $shortLocaleMonth the abbreviated month in current locale LC_TIME
+ * @property int $milliseconds
+ * @property int $millisecond
+ * @property int $milli
+ * @property int $week 1 through 53
+ * @property int $isoWeek 1 through 53
+ * @property int $weekYear year according to week format
+ * @property int $isoWeekYear year according to ISO week format
+ * @property int $dayOfYear 1 through 366
+ * @property int $age does a diffInYears() with default parameters
+ * @property int $offset the timezone offset in seconds from UTC
+ * @property int $offsetMinutes the timezone offset in minutes from UTC
+ * @property int $offsetHours the timezone offset in hours from UTC
+ * @property CarbonTimeZone $timezone the current timezone
+ * @property CarbonTimeZone $tz alias of $timezone
+ * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
+ * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday)
+ * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
+ * @property-read int $daysInMonth number of days in the given month
+ * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
+ * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
+ * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
+ * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
+ * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
+ * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
+ * @property-read int $noZeroHour current hour from 1 to 24
+ * @property-read int $weeksInYear 51 through 53
+ * @property-read int $isoWeeksInYear 51 through 53
+ * @property-read int $weekOfMonth 1 through 5
+ * @property-read int $weekNumberInMonth 1 through 5
+ * @property-read int $firstWeekDay 0 through 6
+ * @property-read int $lastWeekDay 0 through 6
+ * @property-read int $daysInYear 365 or 366
+ * @property-read int $quarter the quarter of this instance, 1 - 4
+ * @property-read int $decade the decade of this instance
+ * @property-read int $century the century of this instance
+ * @property-read int $millennium the millennium of this instance
+ * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
+ * @property-read bool $local checks if the timezone is local, true if local, false otherwise
+ * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
+ * @property-read string $timezoneName the current timezone name
+ * @property-read string $tzName alias of $timezoneName
+ * @property-read string $locale locale of the current instance
+ *
+ * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
+ * @method bool isLocal() Check if the current instance has non-UTC timezone.
+ * @method bool isValid() Check if the current instance is a valid date.
+ * @method bool isDST() Check if the current instance is in a daylight saving time.
+ * @method bool isSunday() Checks if the instance day is sunday.
+ * @method bool isMonday() Checks if the instance day is monday.
+ * @method bool isTuesday() Checks if the instance day is tuesday.
+ * @method bool isWednesday() Checks if the instance day is wednesday.
+ * @method bool isThursday() Checks if the instance day is thursday.
+ * @method bool isFriday() Checks if the instance day is friday.
+ * @method bool isSaturday() Checks if the instance day is saturday.
+ * @method bool isSameYear(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment.
+ * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year.
+ * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year.
+ * @method bool isSameWeek(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment.
+ * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week.
+ * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week.
+ * @method bool isSameDay(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment.
+ * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day.
+ * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day.
+ * @method bool isSameHour(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment.
+ * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour.
+ * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour.
+ * @method bool isSameMinute(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment.
+ * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute.
+ * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute.
+ * @method bool isSameSecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment.
+ * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second.
+ * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second.
+ * @method bool isSameMicro(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment.
+ * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond.
+ * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond.
+ * @method bool isSameMicrosecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment.
+ * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond.
+ * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond.
+ * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment.
+ * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month.
+ * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month.
+ * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment.
+ * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter.
+ * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter.
+ * @method bool isSameDecade(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment.
+ * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade.
+ * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade.
+ * @method bool isSameCentury(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment.
+ * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century.
+ * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century.
+ * @method bool isSameMillennium(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment.
+ * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium.
+ * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium.
+ * @method $this years(int $value) Set current instance year to the given value.
+ * @method $this year(int $value) Set current instance year to the given value.
+ * @method $this setYears(int $value) Set current instance year to the given value.
+ * @method $this setYear(int $value) Set current instance year to the given value.
+ * @method $this months(int $value) Set current instance month to the given value.
+ * @method $this month(int $value) Set current instance month to the given value.
+ * @method $this setMonths(int $value) Set current instance month to the given value.
+ * @method $this setMonth(int $value) Set current instance month to the given value.
+ * @method $this days(int $value) Set current instance day to the given value.
+ * @method $this day(int $value) Set current instance day to the given value.
+ * @method $this setDays(int $value) Set current instance day to the given value.
+ * @method $this setDay(int $value) Set current instance day to the given value.
+ * @method $this hours(int $value) Set current instance hour to the given value.
+ * @method $this hour(int $value) Set current instance hour to the given value.
+ * @method $this setHours(int $value) Set current instance hour to the given value.
+ * @method $this setHour(int $value) Set current instance hour to the given value.
+ * @method $this minutes(int $value) Set current instance minute to the given value.
+ * @method $this minute(int $value) Set current instance minute to the given value.
+ * @method $this setMinutes(int $value) Set current instance minute to the given value.
+ * @method $this setMinute(int $value) Set current instance minute to the given value.
+ * @method $this seconds(int $value) Set current instance second to the given value.
+ * @method $this second(int $value) Set current instance second to the given value.
+ * @method $this setSeconds(int $value) Set current instance second to the given value.
+ * @method $this setSecond(int $value) Set current instance second to the given value.
+ * @method $this millis(int $value) Set current instance millisecond to the given value.
+ * @method $this milli(int $value) Set current instance millisecond to the given value.
+ * @method $this setMillis(int $value) Set current instance millisecond to the given value.
+ * @method $this setMilli(int $value) Set current instance millisecond to the given value.
+ * @method $this milliseconds(int $value) Set current instance millisecond to the given value.
+ * @method $this millisecond(int $value) Set current instance millisecond to the given value.
+ * @method $this setMilliseconds(int $value) Set current instance millisecond to the given value.
+ * @method $this setMillisecond(int $value) Set current instance millisecond to the given value.
+ * @method $this micros(int $value) Set current instance microsecond to the given value.
+ * @method $this micro(int $value) Set current instance microsecond to the given value.
+ * @method $this setMicros(int $value) Set current instance microsecond to the given value.
+ * @method $this setMicro(int $value) Set current instance microsecond to the given value.
+ * @method $this microseconds(int $value) Set current instance microsecond to the given value.
+ * @method $this microsecond(int $value) Set current instance microsecond to the given value.
+ * @method $this setMicroseconds(int $value) Set current instance microsecond to the given value.
+ * @method $this setMicrosecond(int $value) Set current instance microsecond to the given value.
+ * @method $this addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval).
+ * @method $this addYear() Add one year to the instance (using date interval).
+ * @method $this subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval).
+ * @method $this subYear() Sub one year to the instance (using date interval).
+ * @method $this addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval).
+ * @method $this addMonth() Add one month to the instance (using date interval).
+ * @method $this subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval).
+ * @method $this subMonth() Sub one month to the instance (using date interval).
+ * @method $this addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval).
+ * @method $this addDay() Add one day to the instance (using date interval).
+ * @method $this subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval).
+ * @method $this subDay() Sub one day to the instance (using date interval).
+ * @method $this addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval).
+ * @method $this addHour() Add one hour to the instance (using date interval).
+ * @method $this subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval).
+ * @method $this subHour() Sub one hour to the instance (using date interval).
+ * @method $this addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval).
+ * @method $this addMinute() Add one minute to the instance (using date interval).
+ * @method $this subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval).
+ * @method $this subMinute() Sub one minute to the instance (using date interval).
+ * @method $this addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval).
+ * @method $this addSecond() Add one second to the instance (using date interval).
+ * @method $this subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval).
+ * @method $this subSecond() Sub one second to the instance (using date interval).
+ * @method $this addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method $this addMilli() Add one millisecond to the instance (using date interval).
+ * @method $this subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method $this subMilli() Sub one millisecond to the instance (using date interval).
+ * @method $this addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method $this addMillisecond() Add one millisecond to the instance (using date interval).
+ * @method $this subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method $this subMillisecond() Sub one millisecond to the instance (using date interval).
+ * @method $this addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
+ * @method $this addMicro() Add one microsecond to the instance (using date interval).
+ * @method $this subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
+ * @method $this subMicro() Sub one microsecond to the instance (using date interval).
+ * @method $this addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
+ * @method $this addMicrosecond() Add one microsecond to the instance (using date interval).
+ * @method $this subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
+ * @method $this subMicrosecond() Sub one microsecond to the instance (using date interval).
+ * @method $this addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval).
+ * @method $this addMillennium() Add one millennium to the instance (using date interval).
+ * @method $this subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval).
+ * @method $this subMillennium() Sub one millennium to the instance (using date interval).
+ * @method $this addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval).
+ * @method $this addCentury() Add one century to the instance (using date interval).
+ * @method $this subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval).
+ * @method $this subCentury() Sub one century to the instance (using date interval).
+ * @method $this addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval).
+ * @method $this addDecade() Add one decade to the instance (using date interval).
+ * @method $this subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval).
+ * @method $this subDecade() Sub one decade to the instance (using date interval).
+ * @method $this addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval).
+ * @method $this addQuarter() Add one quarter to the instance (using date interval).
+ * @method $this subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval).
+ * @method $this subQuarter() Sub one quarter to the instance (using date interval).
+ * @method $this addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
+ * @method $this addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method $this addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval).
+ * @method $this addWeek() Add one week to the instance (using date interval).
+ * @method $this subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval).
+ * @method $this subWeek() Sub one week to the instance (using date interval).
+ * @method $this addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval).
+ * @method $this addWeekday() Add one weekday to the instance (using date interval).
+ * @method $this subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval).
+ * @method $this subWeekday() Sub one weekday to the instance (using date interval).
+ * @method $this addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealMicro() Add one microsecond to the instance (using timestamp).
+ * @method $this subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealMicro() Sub one microsecond to the instance (using timestamp).
+ * @method CarbonPeriod microsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
+ * @method $this addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealMicrosecond() Add one microsecond to the instance (using timestamp).
+ * @method $this subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealMicrosecond() Sub one microsecond to the instance (using timestamp).
+ * @method CarbonPeriod microsecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
+ * @method $this addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealMilli() Add one millisecond to the instance (using timestamp).
+ * @method $this subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealMilli() Sub one millisecond to the instance (using timestamp).
+ * @method CarbonPeriod millisUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
+ * @method $this addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealMillisecond() Add one millisecond to the instance (using timestamp).
+ * @method $this subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealMillisecond() Sub one millisecond to the instance (using timestamp).
+ * @method CarbonPeriod millisecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
+ * @method $this addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealSecond() Add one second to the instance (using timestamp).
+ * @method $this subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealSecond() Sub one second to the instance (using timestamp).
+ * @method CarbonPeriod secondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given.
+ * @method $this addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealMinute() Add one minute to the instance (using timestamp).
+ * @method $this subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealMinute() Sub one minute to the instance (using timestamp).
+ * @method CarbonPeriod minutesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given.
+ * @method $this addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealHour() Add one hour to the instance (using timestamp).
+ * @method $this subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealHour() Sub one hour to the instance (using timestamp).
+ * @method CarbonPeriod hoursUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given.
+ * @method $this addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealDay() Add one day to the instance (using timestamp).
+ * @method $this subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealDay() Sub one day to the instance (using timestamp).
+ * @method CarbonPeriod daysUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given.
+ * @method $this addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealWeek() Add one week to the instance (using timestamp).
+ * @method $this subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealWeek() Sub one week to the instance (using timestamp).
+ * @method CarbonPeriod weeksUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given.
+ * @method $this addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealMonth() Add one month to the instance (using timestamp).
+ * @method $this subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealMonth() Sub one month to the instance (using timestamp).
+ * @method CarbonPeriod monthsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given.
+ * @method $this addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealQuarter() Add one quarter to the instance (using timestamp).
+ * @method $this subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealQuarter() Sub one quarter to the instance (using timestamp).
+ * @method CarbonPeriod quartersUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given.
+ * @method $this addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealYear() Add one year to the instance (using timestamp).
+ * @method $this subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealYear() Sub one year to the instance (using timestamp).
+ * @method CarbonPeriod yearsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given.
+ * @method $this addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealDecade() Add one decade to the instance (using timestamp).
+ * @method $this subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealDecade() Sub one decade to the instance (using timestamp).
+ * @method CarbonPeriod decadesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given.
+ * @method $this addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealCentury() Add one century to the instance (using timestamp).
+ * @method $this subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealCentury() Sub one century to the instance (using timestamp).
+ * @method CarbonPeriod centuriesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given.
+ * @method $this addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp).
+ * @method $this addRealMillennium() Add one millennium to the instance (using timestamp).
+ * @method $this subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp).
+ * @method $this subRealMillennium() Sub one millennium to the instance (using timestamp).
+ * @method CarbonPeriod millenniaUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given.
+ * @method $this roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method $this roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method $this floorYear(float $precision = 1) Truncate the current instance year with given precision.
+ * @method $this floorYears(float $precision = 1) Truncate the current instance year with given precision.
+ * @method $this ceilYear(float $precision = 1) Ceil the current instance year with given precision.
+ * @method $this ceilYears(float $precision = 1) Ceil the current instance year with given precision.
+ * @method $this roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method $this roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method $this floorMonth(float $precision = 1) Truncate the current instance month with given precision.
+ * @method $this floorMonths(float $precision = 1) Truncate the current instance month with given precision.
+ * @method $this ceilMonth(float $precision = 1) Ceil the current instance month with given precision.
+ * @method $this ceilMonths(float $precision = 1) Ceil the current instance month with given precision.
+ * @method $this roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method $this roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method $this floorDay(float $precision = 1) Truncate the current instance day with given precision.
+ * @method $this floorDays(float $precision = 1) Truncate the current instance day with given precision.
+ * @method $this ceilDay(float $precision = 1) Ceil the current instance day with given precision.
+ * @method $this ceilDays(float $precision = 1) Ceil the current instance day with given precision.
+ * @method $this roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method $this roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method $this floorHour(float $precision = 1) Truncate the current instance hour with given precision.
+ * @method $this floorHours(float $precision = 1) Truncate the current instance hour with given precision.
+ * @method $this ceilHour(float $precision = 1) Ceil the current instance hour with given precision.
+ * @method $this ceilHours(float $precision = 1) Ceil the current instance hour with given precision.
+ * @method $this roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method $this roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method $this floorMinute(float $precision = 1) Truncate the current instance minute with given precision.
+ * @method $this floorMinutes(float $precision = 1) Truncate the current instance minute with given precision.
+ * @method $this ceilMinute(float $precision = 1) Ceil the current instance minute with given precision.
+ * @method $this ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision.
+ * @method $this roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method $this roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method $this floorSecond(float $precision = 1) Truncate the current instance second with given precision.
+ * @method $this floorSeconds(float $precision = 1) Truncate the current instance second with given precision.
+ * @method $this ceilSecond(float $precision = 1) Ceil the current instance second with given precision.
+ * @method $this ceilSeconds(float $precision = 1) Ceil the current instance second with given precision.
+ * @method $this roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method $this roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method $this floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method $this floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method $this ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method $this ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method $this roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method $this roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method $this floorCentury(float $precision = 1) Truncate the current instance century with given precision.
+ * @method $this floorCenturies(float $precision = 1) Truncate the current instance century with given precision.
+ * @method $this ceilCentury(float $precision = 1) Ceil the current instance century with given precision.
+ * @method $this ceilCenturies(float $precision = 1) Ceil the current instance century with given precision.
+ * @method $this roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method $this roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method $this floorDecade(float $precision = 1) Truncate the current instance decade with given precision.
+ * @method $this floorDecades(float $precision = 1) Truncate the current instance decade with given precision.
+ * @method $this ceilDecade(float $precision = 1) Ceil the current instance decade with given precision.
+ * @method $this ceilDecades(float $precision = 1) Ceil the current instance decade with given precision.
+ * @method $this roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method $this roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method $this floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method $this floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method $this ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method $this ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method $this roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method $this roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method $this floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method $this floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method $this ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method $this ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method $this roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method $this roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method $this floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method $this floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method $this ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision.
+ * @method $this ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision.
+ * @method string shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method static Carbon|false createFromFormat(string $format, string $time, string|DateTimeZone $timezone = null) Parse a string into a new Carbon object according to the specified format.
+ * @method static Carbon __set_state(array $array) https://php.net/manual/en/datetime.set-state.php
+ *
+ * </autodoc>
+ */
+class Carbon extends DateTime implements CarbonInterface
+{
+ use Date;
+
+ /**
+ * Returns true if the current class/instance is mutable.
+ *
+ * @return bool
+ */
+ public static function isMutable()
+ {
+ return true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonConverterInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonConverterInterface.php
new file mode 100644
index 0000000..eb0a709
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonConverterInterface.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use DateTimeInterface;
+
+interface CarbonConverterInterface
+{
+ public function convertDate(DateTimeInterface $dateTime, bool $negated = false): CarbonInterface;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonImmutable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonImmutable.php
new file mode 100644
index 0000000..cb1c498
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonImmutable.php
@@ -0,0 +1,582 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use Carbon\Traits\Date;
+use DateTimeImmutable;
+use DateTimeInterface;
+use DateTimeZone;
+
+/**
+ * A simple API extension for DateTimeImmutable.
+ *
+ * <autodoc generated by `composer phpdoc`>
+ *
+ * @property int $year
+ * @property int $yearIso
+ * @property int $month
+ * @property int $day
+ * @property int $hour
+ * @property int $minute
+ * @property int $second
+ * @property int $micro
+ * @property int $microsecond
+ * @property int|float|string $timestamp seconds since the Unix Epoch
+ * @property string $englishDayOfWeek the day of week in English
+ * @property string $shortEnglishDayOfWeek the abbreviated day of week in English
+ * @property string $englishMonth the month in English
+ * @property string $shortEnglishMonth the abbreviated month in English
+ * @property string $localeDayOfWeek the day of week in current locale LC_TIME
+ * @property string $shortLocaleDayOfWeek the abbreviated day of week in current locale LC_TIME
+ * @property string $localeMonth the month in current locale LC_TIME
+ * @property string $shortLocaleMonth the abbreviated month in current locale LC_TIME
+ * @property int $milliseconds
+ * @property int $millisecond
+ * @property int $milli
+ * @property int $week 1 through 53
+ * @property int $isoWeek 1 through 53
+ * @property int $weekYear year according to week format
+ * @property int $isoWeekYear year according to ISO week format
+ * @property int $dayOfYear 1 through 366
+ * @property int $age does a diffInYears() with default parameters
+ * @property int $offset the timezone offset in seconds from UTC
+ * @property int $offsetMinutes the timezone offset in minutes from UTC
+ * @property int $offsetHours the timezone offset in hours from UTC
+ * @property CarbonTimeZone $timezone the current timezone
+ * @property CarbonTimeZone $tz alias of $timezone
+ * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
+ * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday)
+ * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
+ * @property-read int $daysInMonth number of days in the given month
+ * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
+ * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
+ * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
+ * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
+ * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
+ * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
+ * @property-read int $noZeroHour current hour from 1 to 24
+ * @property-read int $weeksInYear 51 through 53
+ * @property-read int $isoWeeksInYear 51 through 53
+ * @property-read int $weekOfMonth 1 through 5
+ * @property-read int $weekNumberInMonth 1 through 5
+ * @property-read int $firstWeekDay 0 through 6
+ * @property-read int $lastWeekDay 0 through 6
+ * @property-read int $daysInYear 365 or 366
+ * @property-read int $quarter the quarter of this instance, 1 - 4
+ * @property-read int $decade the decade of this instance
+ * @property-read int $century the century of this instance
+ * @property-read int $millennium the millennium of this instance
+ * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
+ * @property-read bool $local checks if the timezone is local, true if local, false otherwise
+ * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
+ * @property-read string $timezoneName the current timezone name
+ * @property-read string $tzName alias of $timezoneName
+ * @property-read string $locale locale of the current instance
+ *
+ * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
+ * @method bool isLocal() Check if the current instance has non-UTC timezone.
+ * @method bool isValid() Check if the current instance is a valid date.
+ * @method bool isDST() Check if the current instance is in a daylight saving time.
+ * @method bool isSunday() Checks if the instance day is sunday.
+ * @method bool isMonday() Checks if the instance day is monday.
+ * @method bool isTuesday() Checks if the instance day is tuesday.
+ * @method bool isWednesday() Checks if the instance day is wednesday.
+ * @method bool isThursday() Checks if the instance day is thursday.
+ * @method bool isFriday() Checks if the instance day is friday.
+ * @method bool isSaturday() Checks if the instance day is saturday.
+ * @method bool isSameYear(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment.
+ * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year.
+ * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year.
+ * @method bool isSameWeek(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment.
+ * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week.
+ * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week.
+ * @method bool isSameDay(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment.
+ * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day.
+ * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day.
+ * @method bool isSameHour(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment.
+ * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour.
+ * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour.
+ * @method bool isSameMinute(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment.
+ * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute.
+ * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute.
+ * @method bool isSameSecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment.
+ * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second.
+ * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second.
+ * @method bool isSameMicro(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment.
+ * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond.
+ * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond.
+ * @method bool isSameMicrosecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment.
+ * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond.
+ * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond.
+ * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment.
+ * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month.
+ * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month.
+ * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment.
+ * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter.
+ * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter.
+ * @method bool isSameDecade(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment.
+ * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade.
+ * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade.
+ * @method bool isSameCentury(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment.
+ * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century.
+ * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century.
+ * @method bool isSameMillennium(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment.
+ * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium.
+ * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium.
+ * @method CarbonImmutable years(int $value) Set current instance year to the given value.
+ * @method CarbonImmutable year(int $value) Set current instance year to the given value.
+ * @method CarbonImmutable setYears(int $value) Set current instance year to the given value.
+ * @method CarbonImmutable setYear(int $value) Set current instance year to the given value.
+ * @method CarbonImmutable months(int $value) Set current instance month to the given value.
+ * @method CarbonImmutable month(int $value) Set current instance month to the given value.
+ * @method CarbonImmutable setMonths(int $value) Set current instance month to the given value.
+ * @method CarbonImmutable setMonth(int $value) Set current instance month to the given value.
+ * @method CarbonImmutable days(int $value) Set current instance day to the given value.
+ * @method CarbonImmutable day(int $value) Set current instance day to the given value.
+ * @method CarbonImmutable setDays(int $value) Set current instance day to the given value.
+ * @method CarbonImmutable setDay(int $value) Set current instance day to the given value.
+ * @method CarbonImmutable hours(int $value) Set current instance hour to the given value.
+ * @method CarbonImmutable hour(int $value) Set current instance hour to the given value.
+ * @method CarbonImmutable setHours(int $value) Set current instance hour to the given value.
+ * @method CarbonImmutable setHour(int $value) Set current instance hour to the given value.
+ * @method CarbonImmutable minutes(int $value) Set current instance minute to the given value.
+ * @method CarbonImmutable minute(int $value) Set current instance minute to the given value.
+ * @method CarbonImmutable setMinutes(int $value) Set current instance minute to the given value.
+ * @method CarbonImmutable setMinute(int $value) Set current instance minute to the given value.
+ * @method CarbonImmutable seconds(int $value) Set current instance second to the given value.
+ * @method CarbonImmutable second(int $value) Set current instance second to the given value.
+ * @method CarbonImmutable setSeconds(int $value) Set current instance second to the given value.
+ * @method CarbonImmutable setSecond(int $value) Set current instance second to the given value.
+ * @method CarbonImmutable millis(int $value) Set current instance millisecond to the given value.
+ * @method CarbonImmutable milli(int $value) Set current instance millisecond to the given value.
+ * @method CarbonImmutable setMillis(int $value) Set current instance millisecond to the given value.
+ * @method CarbonImmutable setMilli(int $value) Set current instance millisecond to the given value.
+ * @method CarbonImmutable milliseconds(int $value) Set current instance millisecond to the given value.
+ * @method CarbonImmutable millisecond(int $value) Set current instance millisecond to the given value.
+ * @method CarbonImmutable setMilliseconds(int $value) Set current instance millisecond to the given value.
+ * @method CarbonImmutable setMillisecond(int $value) Set current instance millisecond to the given value.
+ * @method CarbonImmutable micros(int $value) Set current instance microsecond to the given value.
+ * @method CarbonImmutable micro(int $value) Set current instance microsecond to the given value.
+ * @method CarbonImmutable setMicros(int $value) Set current instance microsecond to the given value.
+ * @method CarbonImmutable setMicro(int $value) Set current instance microsecond to the given value.
+ * @method CarbonImmutable microseconds(int $value) Set current instance microsecond to the given value.
+ * @method CarbonImmutable microsecond(int $value) Set current instance microsecond to the given value.
+ * @method CarbonImmutable setMicroseconds(int $value) Set current instance microsecond to the given value.
+ * @method CarbonImmutable setMicrosecond(int $value) Set current instance microsecond to the given value.
+ * @method CarbonImmutable addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addYear() Add one year to the instance (using date interval).
+ * @method CarbonImmutable subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subYear() Sub one year to the instance (using date interval).
+ * @method CarbonImmutable addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addMonth() Add one month to the instance (using date interval).
+ * @method CarbonImmutable subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subMonth() Sub one month to the instance (using date interval).
+ * @method CarbonImmutable addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addDay() Add one day to the instance (using date interval).
+ * @method CarbonImmutable subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subDay() Sub one day to the instance (using date interval).
+ * @method CarbonImmutable addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addHour() Add one hour to the instance (using date interval).
+ * @method CarbonImmutable subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subHour() Sub one hour to the instance (using date interval).
+ * @method CarbonImmutable addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addMinute() Add one minute to the instance (using date interval).
+ * @method CarbonImmutable subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subMinute() Sub one minute to the instance (using date interval).
+ * @method CarbonImmutable addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addSecond() Add one second to the instance (using date interval).
+ * @method CarbonImmutable subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subSecond() Sub one second to the instance (using date interval).
+ * @method CarbonImmutable addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addMilli() Add one millisecond to the instance (using date interval).
+ * @method CarbonImmutable subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subMilli() Sub one millisecond to the instance (using date interval).
+ * @method CarbonImmutable addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addMillisecond() Add one millisecond to the instance (using date interval).
+ * @method CarbonImmutable subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subMillisecond() Sub one millisecond to the instance (using date interval).
+ * @method CarbonImmutable addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addMicro() Add one microsecond to the instance (using date interval).
+ * @method CarbonImmutable subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subMicro() Sub one microsecond to the instance (using date interval).
+ * @method CarbonImmutable addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addMicrosecond() Add one microsecond to the instance (using date interval).
+ * @method CarbonImmutable subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subMicrosecond() Sub one microsecond to the instance (using date interval).
+ * @method CarbonImmutable addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addMillennium() Add one millennium to the instance (using date interval).
+ * @method CarbonImmutable subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subMillennium() Sub one millennium to the instance (using date interval).
+ * @method CarbonImmutable addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addCentury() Add one century to the instance (using date interval).
+ * @method CarbonImmutable subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subCentury() Sub one century to the instance (using date interval).
+ * @method CarbonImmutable addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addDecade() Add one decade to the instance (using date interval).
+ * @method CarbonImmutable subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subDecade() Sub one decade to the instance (using date interval).
+ * @method CarbonImmutable addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addQuarter() Add one quarter to the instance (using date interval).
+ * @method CarbonImmutable subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subQuarter() Sub one quarter to the instance (using date interval).
+ * @method CarbonImmutable addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonImmutable addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonImmutable addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addWeek() Add one week to the instance (using date interval).
+ * @method CarbonImmutable subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subWeek() Sub one week to the instance (using date interval).
+ * @method CarbonImmutable addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable addWeekday() Add one weekday to the instance (using date interval).
+ * @method CarbonImmutable subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval).
+ * @method CarbonImmutable subWeekday() Sub one weekday to the instance (using date interval).
+ * @method CarbonImmutable addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealMicro() Add one microsecond to the instance (using timestamp).
+ * @method CarbonImmutable subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealMicro() Sub one microsecond to the instance (using timestamp).
+ * @method CarbonPeriod microsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
+ * @method CarbonImmutable addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealMicrosecond() Add one microsecond to the instance (using timestamp).
+ * @method CarbonImmutable subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealMicrosecond() Sub one microsecond to the instance (using timestamp).
+ * @method CarbonPeriod microsecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
+ * @method CarbonImmutable addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealMilli() Add one millisecond to the instance (using timestamp).
+ * @method CarbonImmutable subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealMilli() Sub one millisecond to the instance (using timestamp).
+ * @method CarbonPeriod millisUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
+ * @method CarbonImmutable addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealMillisecond() Add one millisecond to the instance (using timestamp).
+ * @method CarbonImmutable subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealMillisecond() Sub one millisecond to the instance (using timestamp).
+ * @method CarbonPeriod millisecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
+ * @method CarbonImmutable addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealSecond() Add one second to the instance (using timestamp).
+ * @method CarbonImmutable subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealSecond() Sub one second to the instance (using timestamp).
+ * @method CarbonPeriod secondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given.
+ * @method CarbonImmutable addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealMinute() Add one minute to the instance (using timestamp).
+ * @method CarbonImmutable subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealMinute() Sub one minute to the instance (using timestamp).
+ * @method CarbonPeriod minutesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given.
+ * @method CarbonImmutable addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealHour() Add one hour to the instance (using timestamp).
+ * @method CarbonImmutable subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealHour() Sub one hour to the instance (using timestamp).
+ * @method CarbonPeriod hoursUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given.
+ * @method CarbonImmutable addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealDay() Add one day to the instance (using timestamp).
+ * @method CarbonImmutable subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealDay() Sub one day to the instance (using timestamp).
+ * @method CarbonPeriod daysUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given.
+ * @method CarbonImmutable addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealWeek() Add one week to the instance (using timestamp).
+ * @method CarbonImmutable subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealWeek() Sub one week to the instance (using timestamp).
+ * @method CarbonPeriod weeksUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given.
+ * @method CarbonImmutable addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealMonth() Add one month to the instance (using timestamp).
+ * @method CarbonImmutable subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealMonth() Sub one month to the instance (using timestamp).
+ * @method CarbonPeriod monthsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given.
+ * @method CarbonImmutable addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealQuarter() Add one quarter to the instance (using timestamp).
+ * @method CarbonImmutable subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealQuarter() Sub one quarter to the instance (using timestamp).
+ * @method CarbonPeriod quartersUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given.
+ * @method CarbonImmutable addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealYear() Add one year to the instance (using timestamp).
+ * @method CarbonImmutable subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealYear() Sub one year to the instance (using timestamp).
+ * @method CarbonPeriod yearsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given.
+ * @method CarbonImmutable addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealDecade() Add one decade to the instance (using timestamp).
+ * @method CarbonImmutable subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealDecade() Sub one decade to the instance (using timestamp).
+ * @method CarbonPeriod decadesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given.
+ * @method CarbonImmutable addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealCentury() Add one century to the instance (using timestamp).
+ * @method CarbonImmutable subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealCentury() Sub one century to the instance (using timestamp).
+ * @method CarbonPeriod centuriesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given.
+ * @method CarbonImmutable addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable addRealMillennium() Add one millennium to the instance (using timestamp).
+ * @method CarbonImmutable subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonImmutable subRealMillennium() Sub one millennium to the instance (using timestamp).
+ * @method CarbonPeriod millenniaUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given.
+ * @method CarbonImmutable roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method CarbonImmutable roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method CarbonImmutable floorYear(float $precision = 1) Truncate the current instance year with given precision.
+ * @method CarbonImmutable floorYears(float $precision = 1) Truncate the current instance year with given precision.
+ * @method CarbonImmutable ceilYear(float $precision = 1) Ceil the current instance year with given precision.
+ * @method CarbonImmutable ceilYears(float $precision = 1) Ceil the current instance year with given precision.
+ * @method CarbonImmutable roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method CarbonImmutable roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method CarbonImmutable floorMonth(float $precision = 1) Truncate the current instance month with given precision.
+ * @method CarbonImmutable floorMonths(float $precision = 1) Truncate the current instance month with given precision.
+ * @method CarbonImmutable ceilMonth(float $precision = 1) Ceil the current instance month with given precision.
+ * @method CarbonImmutable ceilMonths(float $precision = 1) Ceil the current instance month with given precision.
+ * @method CarbonImmutable roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method CarbonImmutable roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method CarbonImmutable floorDay(float $precision = 1) Truncate the current instance day with given precision.
+ * @method CarbonImmutable floorDays(float $precision = 1) Truncate the current instance day with given precision.
+ * @method CarbonImmutable ceilDay(float $precision = 1) Ceil the current instance day with given precision.
+ * @method CarbonImmutable ceilDays(float $precision = 1) Ceil the current instance day with given precision.
+ * @method CarbonImmutable roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method CarbonImmutable roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method CarbonImmutable floorHour(float $precision = 1) Truncate the current instance hour with given precision.
+ * @method CarbonImmutable floorHours(float $precision = 1) Truncate the current instance hour with given precision.
+ * @method CarbonImmutable ceilHour(float $precision = 1) Ceil the current instance hour with given precision.
+ * @method CarbonImmutable ceilHours(float $precision = 1) Ceil the current instance hour with given precision.
+ * @method CarbonImmutable roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method CarbonImmutable roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method CarbonImmutable floorMinute(float $precision = 1) Truncate the current instance minute with given precision.
+ * @method CarbonImmutable floorMinutes(float $precision = 1) Truncate the current instance minute with given precision.
+ * @method CarbonImmutable ceilMinute(float $precision = 1) Ceil the current instance minute with given precision.
+ * @method CarbonImmutable ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision.
+ * @method CarbonImmutable roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method CarbonImmutable roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method CarbonImmutable floorSecond(float $precision = 1) Truncate the current instance second with given precision.
+ * @method CarbonImmutable floorSeconds(float $precision = 1) Truncate the current instance second with given precision.
+ * @method CarbonImmutable ceilSecond(float $precision = 1) Ceil the current instance second with given precision.
+ * @method CarbonImmutable ceilSeconds(float $precision = 1) Ceil the current instance second with given precision.
+ * @method CarbonImmutable roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method CarbonImmutable roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method CarbonImmutable floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method CarbonImmutable floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method CarbonImmutable ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method CarbonImmutable ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method CarbonImmutable roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method CarbonImmutable roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method CarbonImmutable floorCentury(float $precision = 1) Truncate the current instance century with given precision.
+ * @method CarbonImmutable floorCenturies(float $precision = 1) Truncate the current instance century with given precision.
+ * @method CarbonImmutable ceilCentury(float $precision = 1) Ceil the current instance century with given precision.
+ * @method CarbonImmutable ceilCenturies(float $precision = 1) Ceil the current instance century with given precision.
+ * @method CarbonImmutable roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method CarbonImmutable roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method CarbonImmutable floorDecade(float $precision = 1) Truncate the current instance decade with given precision.
+ * @method CarbonImmutable floorDecades(float $precision = 1) Truncate the current instance decade with given precision.
+ * @method CarbonImmutable ceilDecade(float $precision = 1) Ceil the current instance decade with given precision.
+ * @method CarbonImmutable ceilDecades(float $precision = 1) Ceil the current instance decade with given precision.
+ * @method CarbonImmutable roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method CarbonImmutable roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method CarbonImmutable floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method CarbonImmutable floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method CarbonImmutable ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method CarbonImmutable ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method CarbonImmutable roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method CarbonImmutable roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method CarbonImmutable floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method CarbonImmutable floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method CarbonImmutable ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method CarbonImmutable ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method CarbonImmutable roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method CarbonImmutable roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method CarbonImmutable floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method CarbonImmutable floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method CarbonImmutable ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision.
+ * @method CarbonImmutable ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision.
+ * @method string shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method static CarbonImmutable|false createFromFormat(string $format, string $time, string|DateTimeZone $timezone = null) Parse a string into a new CarbonImmutable object according to the specified format.
+ * @method static CarbonImmutable __set_state(array $array) https://php.net/manual/en/datetime.set-state.php
+ *
+ * </autodoc>
+ */
+class CarbonImmutable extends DateTimeImmutable implements CarbonInterface
+{
+ use Date {
+ __clone as dateTraitClone;
+ }
+
+ public function __clone()
+ {
+ $this->dateTraitClone();
+ $this->endOfTime = false;
+ $this->startOfTime = false;
+ }
+
+ /**
+ * Create a very old date representing start of time.
+ *
+ * @return static
+ */
+ public static function startOfTime(): self
+ {
+ $date = static::parse('0001-01-01')->years(self::getStartOfTimeYear());
+ $date->startOfTime = true;
+
+ return $date;
+ }
+
+ /**
+ * Create a very far date representing end of time.
+ *
+ * @return static
+ */
+ public static function endOfTime(): self
+ {
+ $date = static::parse('9999-12-31 23:59:59.999999')->years(self::getEndOfTimeYear());
+ $date->endOfTime = true;
+
+ return $date;
+ }
+
+ /**
+ * @codeCoverageIgnore
+ */
+ private static function getEndOfTimeYear(): int
+ {
+ if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) {
+ return 145261681241552;
+ }
+
+ // Remove if https://bugs.php.net/bug.php?id=81107 is fixed
+ if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) {
+ return 1118290769066902787;
+ }
+
+ return PHP_INT_MAX;
+ }
+
+ /**
+ * @codeCoverageIgnore
+ */
+ private static function getStartOfTimeYear(): int
+ {
+ if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) {
+ return -135908816449551;
+ }
+
+ // Remove if https://bugs.php.net/bug.php?id=81107 is fixed
+ if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) {
+ return -1118290769066898816;
+ }
+
+ return max(PHP_INT_MIN, -9223372036854773760);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterface.php
new file mode 100644
index 0000000..8f09507
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterface.php
@@ -0,0 +1,5032 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use BadMethodCallException;
+use Carbon\Exceptions\BadComparisonUnitException;
+use Carbon\Exceptions\ImmutableException;
+use Carbon\Exceptions\InvalidDateException;
+use Carbon\Exceptions\InvalidFormatException;
+use Carbon\Exceptions\UnknownGetterException;
+use Carbon\Exceptions\UnknownMethodException;
+use Carbon\Exceptions\UnknownSetterException;
+use Closure;
+use DateInterval;
+use DateTime;
+use DateTimeImmutable;
+use DateTimeInterface;
+use DateTimeZone;
+use JsonSerializable;
+use ReflectionException;
+use ReturnTypeWillChange;
+use Throwable;
+
+/**
+ * Common interface for Carbon and CarbonImmutable.
+ *
+ * <autodoc generated by `composer phpdoc`>
+ *
+ * @property int $year
+ * @property int $yearIso
+ * @property int $month
+ * @property int $day
+ * @property int $hour
+ * @property int $minute
+ * @property int $second
+ * @property int $micro
+ * @property int $microsecond
+ * @property int|float|string $timestamp seconds since the Unix Epoch
+ * @property string $englishDayOfWeek the day of week in English
+ * @property string $shortEnglishDayOfWeek the abbreviated day of week in English
+ * @property string $englishMonth the month in English
+ * @property string $shortEnglishMonth the abbreviated month in English
+ * @property string $localeDayOfWeek the day of week in current locale LC_TIME
+ * @property string $shortLocaleDayOfWeek the abbreviated day of week in current locale LC_TIME
+ * @property string $localeMonth the month in current locale LC_TIME
+ * @property string $shortLocaleMonth the abbreviated month in current locale LC_TIME
+ * @property int $milliseconds
+ * @property int $millisecond
+ * @property int $milli
+ * @property int $week 1 through 53
+ * @property int $isoWeek 1 through 53
+ * @property int $weekYear year according to week format
+ * @property int $isoWeekYear year according to ISO week format
+ * @property int $dayOfYear 1 through 366
+ * @property int $age does a diffInYears() with default parameters
+ * @property int $offset the timezone offset in seconds from UTC
+ * @property int $offsetMinutes the timezone offset in minutes from UTC
+ * @property int $offsetHours the timezone offset in hours from UTC
+ * @property CarbonTimeZone $timezone the current timezone
+ * @property CarbonTimeZone $tz alias of $timezone
+ * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
+ * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday)
+ * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
+ * @property-read int $daysInMonth number of days in the given month
+ * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
+ * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
+ * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
+ * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
+ * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
+ * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
+ * @property-read int $noZeroHour current hour from 1 to 24
+ * @property-read int $weeksInYear 51 through 53
+ * @property-read int $isoWeeksInYear 51 through 53
+ * @property-read int $weekOfMonth 1 through 5
+ * @property-read int $weekNumberInMonth 1 through 5
+ * @property-read int $firstWeekDay 0 through 6
+ * @property-read int $lastWeekDay 0 through 6
+ * @property-read int $daysInYear 365 or 366
+ * @property-read int $quarter the quarter of this instance, 1 - 4
+ * @property-read int $decade the decade of this instance
+ * @property-read int $century the century of this instance
+ * @property-read int $millennium the millennium of this instance
+ * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
+ * @property-read bool $local checks if the timezone is local, true if local, false otherwise
+ * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
+ * @property-read string $timezoneName the current timezone name
+ * @property-read string $tzName alias of $timezoneName
+ * @property-read string $locale locale of the current instance
+ *
+ * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
+ * @method bool isLocal() Check if the current instance has non-UTC timezone.
+ * @method bool isValid() Check if the current instance is a valid date.
+ * @method bool isDST() Check if the current instance is in a daylight saving time.
+ * @method bool isSunday() Checks if the instance day is sunday.
+ * @method bool isMonday() Checks if the instance day is monday.
+ * @method bool isTuesday() Checks if the instance day is tuesday.
+ * @method bool isWednesday() Checks if the instance day is wednesday.
+ * @method bool isThursday() Checks if the instance day is thursday.
+ * @method bool isFriday() Checks if the instance day is friday.
+ * @method bool isSaturday() Checks if the instance day is saturday.
+ * @method bool isSameYear(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment.
+ * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year.
+ * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year.
+ * @method bool isSameWeek(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment.
+ * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week.
+ * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week.
+ * @method bool isSameDay(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment.
+ * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day.
+ * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day.
+ * @method bool isSameHour(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment.
+ * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour.
+ * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour.
+ * @method bool isSameMinute(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment.
+ * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute.
+ * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute.
+ * @method bool isSameSecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment.
+ * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second.
+ * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second.
+ * @method bool isSameMicro(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment.
+ * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond.
+ * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond.
+ * @method bool isSameMicrosecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment.
+ * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond.
+ * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond.
+ * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment.
+ * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month.
+ * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month.
+ * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment.
+ * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter.
+ * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter.
+ * @method bool isSameDecade(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment.
+ * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade.
+ * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade.
+ * @method bool isSameCentury(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment.
+ * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century.
+ * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century.
+ * @method bool isSameMillennium(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment.
+ * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium.
+ * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium.
+ * @method CarbonInterface years(int $value) Set current instance year to the given value.
+ * @method CarbonInterface year(int $value) Set current instance year to the given value.
+ * @method CarbonInterface setYears(int $value) Set current instance year to the given value.
+ * @method CarbonInterface setYear(int $value) Set current instance year to the given value.
+ * @method CarbonInterface months(int $value) Set current instance month to the given value.
+ * @method CarbonInterface month(int $value) Set current instance month to the given value.
+ * @method CarbonInterface setMonths(int $value) Set current instance month to the given value.
+ * @method CarbonInterface setMonth(int $value) Set current instance month to the given value.
+ * @method CarbonInterface days(int $value) Set current instance day to the given value.
+ * @method CarbonInterface day(int $value) Set current instance day to the given value.
+ * @method CarbonInterface setDays(int $value) Set current instance day to the given value.
+ * @method CarbonInterface setDay(int $value) Set current instance day to the given value.
+ * @method CarbonInterface hours(int $value) Set current instance hour to the given value.
+ * @method CarbonInterface hour(int $value) Set current instance hour to the given value.
+ * @method CarbonInterface setHours(int $value) Set current instance hour to the given value.
+ * @method CarbonInterface setHour(int $value) Set current instance hour to the given value.
+ * @method CarbonInterface minutes(int $value) Set current instance minute to the given value.
+ * @method CarbonInterface minute(int $value) Set current instance minute to the given value.
+ * @method CarbonInterface setMinutes(int $value) Set current instance minute to the given value.
+ * @method CarbonInterface setMinute(int $value) Set current instance minute to the given value.
+ * @method CarbonInterface seconds(int $value) Set current instance second to the given value.
+ * @method CarbonInterface second(int $value) Set current instance second to the given value.
+ * @method CarbonInterface setSeconds(int $value) Set current instance second to the given value.
+ * @method CarbonInterface setSecond(int $value) Set current instance second to the given value.
+ * @method CarbonInterface millis(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface milli(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface setMillis(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface setMilli(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface milliseconds(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface millisecond(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface setMilliseconds(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface setMillisecond(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface micros(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface micro(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface setMicros(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface setMicro(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface microseconds(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface microsecond(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface setMicroseconds(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface setMicrosecond(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addYear() Add one year to the instance (using date interval).
+ * @method CarbonInterface subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subYear() Sub one year to the instance (using date interval).
+ * @method CarbonInterface addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMonth() Add one month to the instance (using date interval).
+ * @method CarbonInterface subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMonth() Sub one month to the instance (using date interval).
+ * @method CarbonInterface addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addDay() Add one day to the instance (using date interval).
+ * @method CarbonInterface subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subDay() Sub one day to the instance (using date interval).
+ * @method CarbonInterface addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addHour() Add one hour to the instance (using date interval).
+ * @method CarbonInterface subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subHour() Sub one hour to the instance (using date interval).
+ * @method CarbonInterface addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMinute() Add one minute to the instance (using date interval).
+ * @method CarbonInterface subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMinute() Sub one minute to the instance (using date interval).
+ * @method CarbonInterface addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addSecond() Add one second to the instance (using date interval).
+ * @method CarbonInterface subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subSecond() Sub one second to the instance (using date interval).
+ * @method CarbonInterface addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMilli() Add one millisecond to the instance (using date interval).
+ * @method CarbonInterface subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMilli() Sub one millisecond to the instance (using date interval).
+ * @method CarbonInterface addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMillisecond() Add one millisecond to the instance (using date interval).
+ * @method CarbonInterface subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMillisecond() Sub one millisecond to the instance (using date interval).
+ * @method CarbonInterface addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMicro() Add one microsecond to the instance (using date interval).
+ * @method CarbonInterface subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMicro() Sub one microsecond to the instance (using date interval).
+ * @method CarbonInterface addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMicrosecond() Add one microsecond to the instance (using date interval).
+ * @method CarbonInterface subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMicrosecond() Sub one microsecond to the instance (using date interval).
+ * @method CarbonInterface addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMillennium() Add one millennium to the instance (using date interval).
+ * @method CarbonInterface subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMillennium() Sub one millennium to the instance (using date interval).
+ * @method CarbonInterface addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addCentury() Add one century to the instance (using date interval).
+ * @method CarbonInterface subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subCentury() Sub one century to the instance (using date interval).
+ * @method CarbonInterface addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addDecade() Add one decade to the instance (using date interval).
+ * @method CarbonInterface subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subDecade() Sub one decade to the instance (using date interval).
+ * @method CarbonInterface addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addQuarter() Add one quarter to the instance (using date interval).
+ * @method CarbonInterface subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subQuarter() Sub one quarter to the instance (using date interval).
+ * @method CarbonInterface addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addWeek() Add one week to the instance (using date interval).
+ * @method CarbonInterface subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subWeek() Sub one week to the instance (using date interval).
+ * @method CarbonInterface addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addWeekday() Add one weekday to the instance (using date interval).
+ * @method CarbonInterface subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subWeekday() Sub one weekday to the instance (using date interval).
+ * @method CarbonInterface addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMicro() Add one microsecond to the instance (using timestamp).
+ * @method CarbonInterface subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMicro() Sub one microsecond to the instance (using timestamp).
+ * @method CarbonPeriod microsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
+ * @method CarbonInterface addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMicrosecond() Add one microsecond to the instance (using timestamp).
+ * @method CarbonInterface subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMicrosecond() Sub one microsecond to the instance (using timestamp).
+ * @method CarbonPeriod microsecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
+ * @method CarbonInterface addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMilli() Add one millisecond to the instance (using timestamp).
+ * @method CarbonInterface subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMilli() Sub one millisecond to the instance (using timestamp).
+ * @method CarbonPeriod millisUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
+ * @method CarbonInterface addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMillisecond() Add one millisecond to the instance (using timestamp).
+ * @method CarbonInterface subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMillisecond() Sub one millisecond to the instance (using timestamp).
+ * @method CarbonPeriod millisecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
+ * @method CarbonInterface addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealSecond() Add one second to the instance (using timestamp).
+ * @method CarbonInterface subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealSecond() Sub one second to the instance (using timestamp).
+ * @method CarbonPeriod secondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given.
+ * @method CarbonInterface addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMinute() Add one minute to the instance (using timestamp).
+ * @method CarbonInterface subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMinute() Sub one minute to the instance (using timestamp).
+ * @method CarbonPeriod minutesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given.
+ * @method CarbonInterface addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealHour() Add one hour to the instance (using timestamp).
+ * @method CarbonInterface subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealHour() Sub one hour to the instance (using timestamp).
+ * @method CarbonPeriod hoursUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given.
+ * @method CarbonInterface addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealDay() Add one day to the instance (using timestamp).
+ * @method CarbonInterface subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealDay() Sub one day to the instance (using timestamp).
+ * @method CarbonPeriod daysUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given.
+ * @method CarbonInterface addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealWeek() Add one week to the instance (using timestamp).
+ * @method CarbonInterface subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealWeek() Sub one week to the instance (using timestamp).
+ * @method CarbonPeriod weeksUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given.
+ * @method CarbonInterface addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMonth() Add one month to the instance (using timestamp).
+ * @method CarbonInterface subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMonth() Sub one month to the instance (using timestamp).
+ * @method CarbonPeriod monthsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given.
+ * @method CarbonInterface addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealQuarter() Add one quarter to the instance (using timestamp).
+ * @method CarbonInterface subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealQuarter() Sub one quarter to the instance (using timestamp).
+ * @method CarbonPeriod quartersUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given.
+ * @method CarbonInterface addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealYear() Add one year to the instance (using timestamp).
+ * @method CarbonInterface subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealYear() Sub one year to the instance (using timestamp).
+ * @method CarbonPeriod yearsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given.
+ * @method CarbonInterface addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealDecade() Add one decade to the instance (using timestamp).
+ * @method CarbonInterface subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealDecade() Sub one decade to the instance (using timestamp).
+ * @method CarbonPeriod decadesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given.
+ * @method CarbonInterface addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealCentury() Add one century to the instance (using timestamp).
+ * @method CarbonInterface subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealCentury() Sub one century to the instance (using timestamp).
+ * @method CarbonPeriod centuriesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given.
+ * @method CarbonInterface addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMillennium() Add one millennium to the instance (using timestamp).
+ * @method CarbonInterface subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMillennium() Sub one millennium to the instance (using timestamp).
+ * @method CarbonPeriod millenniaUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given.
+ * @method CarbonInterface roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method CarbonInterface roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method CarbonInterface floorYear(float $precision = 1) Truncate the current instance year with given precision.
+ * @method CarbonInterface floorYears(float $precision = 1) Truncate the current instance year with given precision.
+ * @method CarbonInterface ceilYear(float $precision = 1) Ceil the current instance year with given precision.
+ * @method CarbonInterface ceilYears(float $precision = 1) Ceil the current instance year with given precision.
+ * @method CarbonInterface roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method CarbonInterface roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method CarbonInterface floorMonth(float $precision = 1) Truncate the current instance month with given precision.
+ * @method CarbonInterface floorMonths(float $precision = 1) Truncate the current instance month with given precision.
+ * @method CarbonInterface ceilMonth(float $precision = 1) Ceil the current instance month with given precision.
+ * @method CarbonInterface ceilMonths(float $precision = 1) Ceil the current instance month with given precision.
+ * @method CarbonInterface roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method CarbonInterface roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method CarbonInterface floorDay(float $precision = 1) Truncate the current instance day with given precision.
+ * @method CarbonInterface floorDays(float $precision = 1) Truncate the current instance day with given precision.
+ * @method CarbonInterface ceilDay(float $precision = 1) Ceil the current instance day with given precision.
+ * @method CarbonInterface ceilDays(float $precision = 1) Ceil the current instance day with given precision.
+ * @method CarbonInterface roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method CarbonInterface roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method CarbonInterface floorHour(float $precision = 1) Truncate the current instance hour with given precision.
+ * @method CarbonInterface floorHours(float $precision = 1) Truncate the current instance hour with given precision.
+ * @method CarbonInterface ceilHour(float $precision = 1) Ceil the current instance hour with given precision.
+ * @method CarbonInterface ceilHours(float $precision = 1) Ceil the current instance hour with given precision.
+ * @method CarbonInterface roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method CarbonInterface roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method CarbonInterface floorMinute(float $precision = 1) Truncate the current instance minute with given precision.
+ * @method CarbonInterface floorMinutes(float $precision = 1) Truncate the current instance minute with given precision.
+ * @method CarbonInterface ceilMinute(float $precision = 1) Ceil the current instance minute with given precision.
+ * @method CarbonInterface ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision.
+ * @method CarbonInterface roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method CarbonInterface roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method CarbonInterface floorSecond(float $precision = 1) Truncate the current instance second with given precision.
+ * @method CarbonInterface floorSeconds(float $precision = 1) Truncate the current instance second with given precision.
+ * @method CarbonInterface ceilSecond(float $precision = 1) Ceil the current instance second with given precision.
+ * @method CarbonInterface ceilSeconds(float $precision = 1) Ceil the current instance second with given precision.
+ * @method CarbonInterface roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method CarbonInterface roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method CarbonInterface floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method CarbonInterface floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method CarbonInterface ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method CarbonInterface ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method CarbonInterface roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method CarbonInterface roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method CarbonInterface floorCentury(float $precision = 1) Truncate the current instance century with given precision.
+ * @method CarbonInterface floorCenturies(float $precision = 1) Truncate the current instance century with given precision.
+ * @method CarbonInterface ceilCentury(float $precision = 1) Ceil the current instance century with given precision.
+ * @method CarbonInterface ceilCenturies(float $precision = 1) Ceil the current instance century with given precision.
+ * @method CarbonInterface roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method CarbonInterface roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method CarbonInterface floorDecade(float $precision = 1) Truncate the current instance decade with given precision.
+ * @method CarbonInterface floorDecades(float $precision = 1) Truncate the current instance decade with given precision.
+ * @method CarbonInterface ceilDecade(float $precision = 1) Ceil the current instance decade with given precision.
+ * @method CarbonInterface ceilDecades(float $precision = 1) Ceil the current instance decade with given precision.
+ * @method CarbonInterface roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method CarbonInterface roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method CarbonInterface floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method CarbonInterface floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method CarbonInterface ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method CarbonInterface ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method CarbonInterface roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method CarbonInterface roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method CarbonInterface floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method CarbonInterface floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method CarbonInterface ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method CarbonInterface ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method CarbonInterface roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method CarbonInterface roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method CarbonInterface floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method CarbonInterface floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method CarbonInterface ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision.
+ * @method CarbonInterface ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision.
+ * @method string shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ *
+ * </autodoc>
+ */
+interface CarbonInterface extends DateTimeInterface, JsonSerializable
+{
+ /**
+ * Diff wording options(expressed in octal).
+ */
+ public const NO_ZERO_DIFF = 01;
+ public const JUST_NOW = 02;
+ public const ONE_DAY_WORDS = 04;
+ public const TWO_DAY_WORDS = 010;
+ public const SEQUENTIAL_PARTS_ONLY = 020;
+ public const ROUND = 040;
+ public const FLOOR = 0100;
+ public const CEIL = 0200;
+
+ /**
+ * Diff syntax options.
+ */
+ public const DIFF_ABSOLUTE = 1; // backward compatibility with true
+ public const DIFF_RELATIVE_AUTO = 0; // backward compatibility with false
+ public const DIFF_RELATIVE_TO_NOW = 2;
+ public const DIFF_RELATIVE_TO_OTHER = 3;
+
+ /**
+ * Translate string options.
+ */
+ public const TRANSLATE_MONTHS = 1;
+ public const TRANSLATE_DAYS = 2;
+ public const TRANSLATE_UNITS = 4;
+ public const TRANSLATE_MERIDIEM = 8;
+ public const TRANSLATE_DIFF = 0x10;
+ public const TRANSLATE_ALL = self::TRANSLATE_MONTHS | self::TRANSLATE_DAYS | self::TRANSLATE_UNITS | self::TRANSLATE_MERIDIEM | self::TRANSLATE_DIFF;
+
+ /**
+ * The day constants.
+ */
+ public const SUNDAY = 0;
+ public const MONDAY = 1;
+ public const TUESDAY = 2;
+ public const WEDNESDAY = 3;
+ public const THURSDAY = 4;
+ public const FRIDAY = 5;
+ public const SATURDAY = 6;
+
+ /**
+ * The month constants.
+ * These aren't used by Carbon itself but exist for
+ * convenience sake alone.
+ */
+ public const JANUARY = 1;
+ public const FEBRUARY = 2;
+ public const MARCH = 3;
+ public const APRIL = 4;
+ public const MAY = 5;
+ public const JUNE = 6;
+ public const JULY = 7;
+ public const AUGUST = 8;
+ public const SEPTEMBER = 9;
+ public const OCTOBER = 10;
+ public const NOVEMBER = 11;
+ public const DECEMBER = 12;
+
+ /**
+ * Number of X in Y.
+ */
+ public const YEARS_PER_MILLENNIUM = 1000;
+ public const YEARS_PER_CENTURY = 100;
+ public const YEARS_PER_DECADE = 10;
+ public const MONTHS_PER_YEAR = 12;
+ public const MONTHS_PER_QUARTER = 3;
+ public const WEEKS_PER_YEAR = 52;
+ public const WEEKS_PER_MONTH = 4;
+ public const DAYS_PER_YEAR = 365;
+ public const DAYS_PER_WEEK = 7;
+ public const HOURS_PER_DAY = 24;
+ public const MINUTES_PER_HOUR = 60;
+ public const SECONDS_PER_MINUTE = 60;
+ public const MILLISECONDS_PER_SECOND = 1000;
+ public const MICROSECONDS_PER_MILLISECOND = 1000;
+ public const MICROSECONDS_PER_SECOND = 1000000;
+
+ /**
+ * Special settings to get the start of week from current locale culture.
+ */
+ public const WEEK_DAY_AUTO = 'auto';
+
+ /**
+ * RFC7231 DateTime format.
+ *
+ * @var string
+ */
+ public const RFC7231_FORMAT = 'D, d M Y H:i:s \G\M\T';
+
+ /**
+ * Default format to use for __toString method when type juggling occurs.
+ *
+ * @var string
+ */
+ public const DEFAULT_TO_STRING_FORMAT = 'Y-m-d H:i:s';
+
+ /**
+ * Format for converting mocked time, includes microseconds.
+ *
+ * @var string
+ */
+ public const MOCK_DATETIME_FORMAT = 'Y-m-d H:i:s.u';
+
+ /**
+ * Pattern detection for ->isoFormat and ::createFromIsoFormat.
+ *
+ * @var string
+ */
+ public const ISO_FORMAT_REGEXP = '(O[YMDHhms]|[Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY?|g{1,5}|G{1,5}|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?)';
+
+ // <methods>
+
+ /**
+ * Dynamically handle calls to the class.
+ *
+ * @param string $method magic method name called
+ * @param array $parameters parameters list
+ *
+ * @throws UnknownMethodException|BadMethodCallException|ReflectionException|Throwable
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters);
+
+ /**
+ * Dynamically handle calls to the class.
+ *
+ * @param string $method magic method name called
+ * @param array $parameters parameters list
+ *
+ * @throws BadMethodCallException
+ *
+ * @return mixed
+ */
+ public static function __callStatic($method, $parameters);
+
+ /**
+ * Update constructedObjectId on cloned.
+ */
+ public function __clone();
+
+ /**
+ * Create a new Carbon instance.
+ *
+ * Please see the testing aids section (specifically static::setTestNow())
+ * for more on the possibility of this constructor returning a test instance.
+ *
+ * @param DateTimeInterface|string|null $time
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ */
+ public function __construct($time = null, $tz = null);
+
+ /**
+ * Show truthy properties on var_dump().
+ *
+ * @return array
+ */
+ public function __debugInfo();
+
+ /**
+ * Get a part of the Carbon object
+ *
+ * @param string $name
+ *
+ * @throws UnknownGetterException
+ *
+ * @return string|int|bool|DateTimeZone|null
+ */
+ public function __get($name);
+
+ /**
+ * Check if an attribute exists on the object
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function __isset($name);
+
+ /**
+ * Set a part of the Carbon object
+ *
+ * @param string $name
+ * @param string|int|DateTimeZone $value
+ *
+ * @throws UnknownSetterException|ReflectionException
+ *
+ * @return void
+ */
+ public function __set($name, $value);
+
+ /**
+ * The __set_state handler.
+ *
+ * @param string|array $dump
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public static function __set_state($dump);
+
+ /**
+ * Returns the list of properties to dump on serialize() called on.
+ *
+ * @return array
+ */
+ public function __sleep();
+
+ /**
+ * Format the instance as a string using the set format
+ *
+ * @example
+ * ```
+ * echo Carbon::now(); // Carbon instances can be casted to string
+ * ```
+ *
+ * @return string
+ */
+ public function __toString();
+
+ /**
+ * Add given units or interval to the current instance.
+ *
+ * @example $date->add('hour', 3)
+ * @example $date->add(15, 'days')
+ * @example $date->add(CarbonInterval::days(4))
+ *
+ * @param string|DateInterval|Closure|CarbonConverterInterface $unit
+ * @param int $value
+ * @param bool|null $overflow
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function add($unit, $value = 1, $overflow = null);
+
+ /**
+ * Add seconds to the instance using timestamp. Positive $value travels
+ * forward while negative $value travels into the past.
+ *
+ * @param string $unit
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addRealUnit($unit, $value = 1);
+
+ /**
+ * Add given units to the current instance.
+ *
+ * @param string $unit
+ * @param int $value
+ * @param bool|null $overflow
+ *
+ * @return static
+ */
+ public function addUnit($unit, $value = 1, $overflow = null);
+
+ /**
+ * Add any unit to a new value without overflowing current other unit given.
+ *
+ * @param string $valueUnit unit name to modify
+ * @param int $value amount to add to the input unit
+ * @param string $overflowUnit unit name to not overflow
+ *
+ * @return static
+ */
+ public function addUnitNoOverflow($valueUnit, $value, $overflowUnit);
+
+ /**
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given to now
+ *
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single part)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function ago($syntax = null, $short = false, $parts = 1, $options = null);
+
+ /**
+ * Modify the current instance to the average of a given instance (default now) and the current instance
+ * (second-precision).
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date
+ *
+ * @return static
+ */
+ public function average($date = null);
+
+ /**
+ * Clone the current instance if it's mutable.
+ *
+ * This method is convenient to ensure you don't mutate the initial object
+ * but avoid to make a useless copy of it if it's already immutable.
+ *
+ * @return static
+ */
+ public function avoidMutation();
+
+ /**
+ * Determines if the instance is between two others.
+ *
+ * The third argument allow you to specify if bounds are included or not (true by default)
+ * but for when you including/excluding bounds may produce different results in your application,
+ * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25')->between('2018-07-14', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->between('2018-08-01', '2018-08-20'); // false
+ * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01', false); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ * @param bool $equal Indicates if an equal to comparison should be done
+ *
+ * @return bool
+ */
+ public function between($date1, $date2, $equal = true): bool;
+
+ /**
+ * Determines if the instance is between two others, bounds excluded.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-14', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->betweenExcluded('2018-08-01', '2018-08-20'); // false
+ * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-25', '2018-08-01'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ *
+ * @return bool
+ */
+ public function betweenExcluded($date1, $date2): bool;
+
+ /**
+ * Determines if the instance is between two others, bounds included.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-14', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->betweenIncluded('2018-08-01', '2018-08-20'); // false
+ * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-25', '2018-08-01'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ *
+ * @return bool
+ */
+ public function betweenIncluded($date1, $date2): bool;
+
+ /**
+ * Returns either day of week + time (e.g. "Last Friday at 3:30 PM") if reference time is within 7 days,
+ * or a calendar date (e.g. "10/29/2017") otherwise.
+ *
+ * Language, date and time formats will change according to the current locale.
+ *
+ * @param Carbon|\DateTimeInterface|string|null $referenceTime
+ * @param array $formats
+ *
+ * @return string
+ */
+ public function calendar($referenceTime = null, array $formats = []);
+
+ /**
+ * Checks if the (date)time string is in a given format and valid to create a
+ * new instance.
+ *
+ * @example
+ * ```
+ * Carbon::canBeCreatedFromFormat('11:12:45', 'h:i:s'); // true
+ * Carbon::canBeCreatedFromFormat('13:12:45', 'h:i:s'); // false
+ * ```
+ *
+ * @param string $date
+ * @param string $format
+ *
+ * @return bool
+ */
+ public static function canBeCreatedFromFormat($date, $format);
+
+ /**
+ * Return the Carbon instance passed through, a now instance in the same timezone
+ * if null given or parse the input if string given.
+ *
+ * @param Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|DateTimeInterface|string|null $date
+ *
+ * @return static
+ */
+ public function carbonize($date = null);
+
+ /**
+ * Cast the current instance into the given class.
+ *
+ * @param string $className The $className::instance() method will be called to cast the current object.
+ *
+ * @return DateTimeInterface
+ */
+ public function cast(string $className);
+
+ /**
+ * Ceil the current instance second with given precision if specified.
+ *
+ * @param float|int|string|\DateInterval|null $precision
+ *
+ * @return CarbonInterface
+ */
+ public function ceil($precision = 1);
+
+ /**
+ * Ceil the current instance at the given unit with given precision if specified.
+ *
+ * @param string $unit
+ * @param float|int $precision
+ *
+ * @return CarbonInterface
+ */
+ public function ceilUnit($unit, $precision = 1);
+
+ /**
+ * Ceil the current instance week.
+ *
+ * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
+ *
+ * @return CarbonInterface
+ */
+ public function ceilWeek($weekStartsAt = null);
+
+ /**
+ * Similar to native modify() method of DateTime but can handle more grammars.
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->change('next 2pm');
+ * ```
+ *
+ * @link https://php.net/manual/en/datetime.modify.php
+ *
+ * @param string $modifier
+ *
+ * @return static
+ */
+ public function change($modifier);
+
+ /**
+ * Cleanup properties attached to the public scope of DateTime when a dump of the date is requested.
+ * foreach ($date as $_) {}
+ * serializer($date)
+ * var_export($date)
+ * get_object_vars($date)
+ */
+ public function cleanupDumpProperties();
+
+ /**
+ * @alias copy
+ *
+ * Get a copy of the instance.
+ *
+ * @return static
+ */
+ public function clone();
+
+ /**
+ * Get the closest date from the instance (second-precision).
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ *
+ * @return static
+ */
+ public function closest($date1, $date2);
+
+ /**
+ * Get a copy of the instance.
+ *
+ * @return static
+ */
+ public function copy();
+
+ /**
+ * Create a new Carbon instance from a specific date and time.
+ *
+ * If any of $year, $month or $day are set to null their now() values will
+ * be used.
+ *
+ * If $hour is null it will be set to its now() value and the default
+ * values for $minute and $second will be their now() values.
+ *
+ * If $hour is not null then the default values for $minute and $second
+ * will be 0.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ public static function create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null);
+
+ /**
+ * Create a Carbon instance from just a date. The time portion is set to now.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function createFromDate($year = null, $month = null, $day = null, $tz = null);
+
+ /**
+ * Create a Carbon instance from a specific format.
+ *
+ * @param string $format Datetime format
+ * @param string $time
+ * @param DateTimeZone|string|false|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ #[ReturnTypeWillChange]
+ public static function createFromFormat($format, $time, $tz = null);
+
+ /**
+ * Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
+ *
+ * @param string $format Datetime format
+ * @param string $time
+ * @param DateTimeZone|string|false|null $tz optional timezone
+ * @param string|null $locale locale to be used for LTS, LT, LL, LLL, etc. macro-formats (en by fault, unneeded if no such macro-format in use)
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator optional custom translator to use for macro-formats
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ public static function createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null);
+
+ /**
+ * Create a Carbon instance from a specific format and a string in a given language.
+ *
+ * @param string $format Datetime format
+ * @param string $locale
+ * @param string $time
+ * @param DateTimeZone|string|false|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ public static function createFromLocaleFormat($format, $locale, $time, $tz = null);
+
+ /**
+ * Create a Carbon instance from a specific ISO format and a string in a given language.
+ *
+ * @param string $format Datetime ISO format
+ * @param string $locale
+ * @param string $time
+ * @param DateTimeZone|string|false|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ public static function createFromLocaleIsoFormat($format, $locale, $time, $tz = null);
+
+ /**
+ * Create a Carbon instance from just a time. The date portion is set to today.
+ *
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null);
+
+ /**
+ * Create a Carbon instance from a time string. The date portion is set to today.
+ *
+ * @param string $time
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function createFromTimeString($time, $tz = null);
+
+ /**
+ * Create a Carbon instance from a timestamp and set the timezone (use default one if not specified).
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $timestamp
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function createFromTimestamp($timestamp, $tz = null);
+
+ /**
+ * Create a Carbon instance from a timestamp in milliseconds.
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $timestamp
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function createFromTimestampMs($timestamp, $tz = null);
+
+ /**
+ * Create a Carbon instance from a timestamp in milliseconds.
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $timestamp
+ *
+ * @return static
+ */
+ public static function createFromTimestampMsUTC($timestamp);
+
+ /**
+ * Create a Carbon instance from an timestamp keeping the timezone to UTC.
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $timestamp
+ *
+ * @return static
+ */
+ public static function createFromTimestampUTC($timestamp);
+
+ /**
+ * Create a Carbon instance from just a date. The time portion is set to midnight.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function createMidnightDate($year = null, $month = null, $day = null, $tz = null);
+
+ /**
+ * Create a new safe Carbon instance from a specific date and time.
+ *
+ * If any of $year, $month or $day are set to null their now() values will
+ * be used.
+ *
+ * If $hour is null it will be set to its now() value and the default
+ * values for $minute and $second will be their now() values.
+ *
+ * If $hour is not null then the default values for $minute and $second
+ * will be 0.
+ *
+ * If one of the set values is not valid, an InvalidDateException
+ * will be thrown.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidDateException
+ *
+ * @return static|false
+ */
+ public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null);
+
+ /**
+ * Create a new Carbon instance from a specific date and time using strict validation.
+ *
+ * @see create()
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null);
+
+ /**
+ * Get/set the day of year.
+ *
+ * @param int|null $value new value for day of year if using as setter.
+ *
+ * @return static|int
+ */
+ public function dayOfYear($value = null);
+
+ /**
+ * Get the difference as a CarbonInterval instance.
+ * Return absolute interval (always positive) unless you pass false to the second argument.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return CarbonInterval
+ */
+ public function diffAsCarbonInterval($date = null, $absolute = true);
+
+ /**
+ * Get the difference by the given interval using a filter closure.
+ *
+ * @param CarbonInterval $ci An interval to traverse by
+ * @param Closure $callback
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, $absolute = true);
+
+ /**
+ * Get the difference in a human readable format in the current locale from current instance to an other
+ * instance given (or now if null given).
+ *
+ * @example
+ * ```
+ * echo Carbon::tomorrow()->diffForHumans() . "\n";
+ * echo Carbon::tomorrow()->diffForHumans(['parts' => 2]) . "\n";
+ * echo Carbon::tomorrow()->diffForHumans(['parts' => 3, 'join' => true]) . "\n";
+ * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday()) . "\n";
+ * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday(), ['short' => true]) . "\n";
+ * ```
+ *
+ * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
+ * if null passed, now will be used as comparison reference;
+ * if any other type, it will be converted to date and used as reference.
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * - 'other' entry (see above)
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single unit)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function diffForHumans($other = null, $syntax = null, $short = false, $parts = 1, $options = null);
+
+ /**
+ * Get the difference in days rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInDays($date = null, $absolute = true);
+
+ /**
+ * Get the difference in days using a filter closure rounded down.
+ *
+ * @param Closure $callback
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInDaysFiltered(Closure $callback, $date = null, $absolute = true);
+
+ /**
+ * Get the difference in hours rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInHours($date = null, $absolute = true);
+
+ /**
+ * Get the difference in hours using a filter closure rounded down.
+ *
+ * @param Closure $callback
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInHoursFiltered(Closure $callback, $date = null, $absolute = true);
+
+ /**
+ * Get the difference in microseconds.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMicroseconds($date = null, $absolute = true);
+
+ /**
+ * Get the difference in milliseconds rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMilliseconds($date = null, $absolute = true);
+
+ /**
+ * Get the difference in minutes rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMinutes($date = null, $absolute = true);
+
+ /**
+ * Get the difference in months rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMonths($date = null, $absolute = true);
+
+ /**
+ * Get the difference in quarters rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInQuarters($date = null, $absolute = true);
+
+ /**
+ * Get the difference in hours rounded down using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealHours($date = null, $absolute = true);
+
+ /**
+ * Get the difference in microseconds using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealMicroseconds($date = null, $absolute = true);
+
+ /**
+ * Get the difference in milliseconds rounded down using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealMilliseconds($date = null, $absolute = true);
+
+ /**
+ * Get the difference in minutes rounded down using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealMinutes($date = null, $absolute = true);
+
+ /**
+ * Get the difference in seconds using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealSeconds($date = null, $absolute = true);
+
+ /**
+ * Get the difference in seconds rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInSeconds($date = null, $absolute = true);
+
+ /**
+ * Get the difference in weekdays rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInWeekdays($date = null, $absolute = true);
+
+ /**
+ * Get the difference in weekend days using a filter rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInWeekendDays($date = null, $absolute = true);
+
+ /**
+ * Get the difference in weeks rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInWeeks($date = null, $absolute = true);
+
+ /**
+ * Get the difference in years
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInYears($date = null, $absolute = true);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @see settings
+ *
+ * @param int $humanDiffOption
+ */
+ public static function disableHumanDiffOption($humanDiffOption);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @see settings
+ *
+ * @param int $humanDiffOption
+ */
+ public static function enableHumanDiffOption($humanDiffOption);
+
+ /**
+ * Modify to end of current given unit.
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16.334455')
+ * ->startOf('month')
+ * ->endOf('week', Carbon::FRIDAY);
+ * ```
+ *
+ * @param string $unit
+ * @param array<int, mixed> $params
+ *
+ * @return static
+ */
+ public function endOf($unit, ...$params);
+
+ /**
+ * Resets the date to end of the century and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfCentury();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfCentury();
+
+ /**
+ * Resets the time to 23:59:59.999999 end of day
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfDay();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfDay();
+
+ /**
+ * Resets the date to end of the decade and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfDecade();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfDecade();
+
+ /**
+ * Modify to end of current hour, minutes and seconds become 59
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfHour();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfHour();
+
+ /**
+ * Resets the date to end of the millennium and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfMillennium();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfMillennium();
+
+ /**
+ * Modify to end of current minute, seconds become 59
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfMinute();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfMinute();
+
+ /**
+ * Resets the date to end of the month and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfMonth();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfMonth();
+
+ /**
+ * Resets the date to end of the quarter and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfQuarter();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfQuarter();
+
+ /**
+ * Modify to end of current second, microseconds become 999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16.334455')
+ * ->endOfSecond()
+ * ->format('H:i:s.u');
+ * ```
+ *
+ * @return static
+ */
+ public function endOfSecond();
+
+ /**
+ * Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek() . "\n";
+ * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->endOfWeek() . "\n";
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek(Carbon::SATURDAY) . "\n";
+ * ```
+ *
+ * @param int $weekEndsAt optional start allow you to specify the day of week to use to end the week
+ *
+ * @return static
+ */
+ public function endOfWeek($weekEndsAt = null);
+
+ /**
+ * Resets the date to end of the year and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfYear();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfYear();
+
+ /**
+ * Determines if the instance is equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->eq(Carbon::parse('2018-07-25 12:45:16')); // true
+ * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see equalTo()
+ *
+ * @return bool
+ */
+ public function eq($date): bool;
+
+ /**
+ * Determines if the instance is equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->equalTo(Carbon::parse('2018-07-25 12:45:16')); // true
+ * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function equalTo($date): bool;
+
+ /**
+ * Set the current locale to the given, execute the passed function, reset the locale to previous one,
+ * then return the result of the closure (or null if the closure was void).
+ *
+ * @param string $locale locale ex. en
+ * @param callable $func
+ *
+ * @return mixed
+ */
+ public static function executeWithLocale($locale, $func);
+
+ /**
+ * Get the farthest date from the instance (second-precision).
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ *
+ * @return static
+ */
+ public function farthest($date1, $date2);
+
+ /**
+ * Modify to the first occurrence of a given day of the week
+ * in the current month. If no dayOfWeek is provided, modify to the
+ * first day of the current month. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek
+ *
+ * @return static
+ */
+ public function firstOfMonth($dayOfWeek = null);
+
+ /**
+ * Modify to the first occurrence of a given day of the week
+ * in the current quarter. If no dayOfWeek is provided, modify to the
+ * first day of the current quarter. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function firstOfQuarter($dayOfWeek = null);
+
+ /**
+ * Modify to the first occurrence of a given day of the week
+ * in the current year. If no dayOfWeek is provided, modify to the
+ * first day of the current year. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function firstOfYear($dayOfWeek = null);
+
+ /**
+ * Get the difference in days as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInDays($date = null, $absolute = true);
+
+ /**
+ * Get the difference in hours as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInHours($date = null, $absolute = true);
+
+ /**
+ * Get the difference in minutes as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInMinutes($date = null, $absolute = true);
+
+ /**
+ * Get the difference in months as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInMonths($date = null, $absolute = true);
+
+ /**
+ * Get the difference in days as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealDays($date = null, $absolute = true);
+
+ /**
+ * Get the difference in hours as float (microsecond-precision) using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealHours($date = null, $absolute = true);
+
+ /**
+ * Get the difference in minutes as float (microsecond-precision) using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealMinutes($date = null, $absolute = true);
+
+ /**
+ * Get the difference in months as float (microsecond-precision) using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealMonths($date = null, $absolute = true);
+
+ /**
+ * Get the difference in seconds as float (microsecond-precision) using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealSeconds($date = null, $absolute = true);
+
+ /**
+ * Get the difference in weeks as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealWeeks($date = null, $absolute = true);
+
+ /**
+ * Get the difference in year as float (microsecond-precision) using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealYears($date = null, $absolute = true);
+
+ /**
+ * Get the difference in seconds as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInSeconds($date = null, $absolute = true);
+
+ /**
+ * Get the difference in weeks as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInWeeks($date = null, $absolute = true);
+
+ /**
+ * Get the difference in year as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInYears($date = null, $absolute = true);
+
+ /**
+ * Round the current instance second with given precision if specified.
+ *
+ * @param float|int|string|\DateInterval|null $precision
+ *
+ * @return CarbonInterface
+ */
+ public function floor($precision = 1);
+
+ /**
+ * Truncate the current instance at the given unit with given precision if specified.
+ *
+ * @param string $unit
+ * @param float|int $precision
+ *
+ * @return CarbonInterface
+ */
+ public function floorUnit($unit, $precision = 1);
+
+ /**
+ * Truncate the current instance week.
+ *
+ * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
+ *
+ * @return CarbonInterface
+ */
+ public function floorWeek($weekStartsAt = null);
+
+ /**
+ * Format the instance with the current locale. You can set the current
+ * locale using setlocale() https://php.net/setlocale.
+ *
+ * @param string $format
+ *
+ * @return string
+ */
+ public function formatLocalized($format);
+
+ /**
+ * @alias diffForHumans
+ *
+ * Get the difference in a human readable format in the current locale from current instance to an other
+ * instance given (or now if null given).
+ *
+ * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
+ * if null passed, now will be used as comparison reference;
+ * if any other type, it will be converted to date and used as reference.
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * - 'other' entry (see above)
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single unit)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function from($other = null, $syntax = null, $short = false, $parts = 1, $options = null);
+
+ /**
+ * Get the difference in a human readable format in the current locale from current
+ * instance to now.
+ *
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single unit)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function fromNow($syntax = null, $short = false, $parts = 1, $options = null);
+
+ /**
+ * Create an instance from a serialized string.
+ *
+ * @param string $value
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function fromSerialized($value);
+
+ /**
+ * Register a custom macro.
+ *
+ * @param object|callable $macro
+ * @param int $priority marco with higher priority is tried first
+ *
+ * @return void
+ */
+ public static function genericMacro($macro, $priority = 0);
+
+ /**
+ * Get a part of the Carbon object
+ *
+ * @param string $name
+ *
+ * @throws UnknownGetterException
+ *
+ * @return string|int|bool|DateTimeZone|null
+ */
+ public function get($name);
+
+ /**
+ * Returns the alternative number for a given date property if available in the current locale.
+ *
+ * @param string $key date property
+ *
+ * @return string
+ */
+ public function getAltNumber(string $key): string;
+
+ /**
+ * Returns the list of internally available locales and already loaded custom locales.
+ * (It will ignore custom translator dynamic loading.)
+ *
+ * @return array
+ */
+ public static function getAvailableLocales();
+
+ /**
+ * Returns list of Language object for each available locale. This object allow you to get the ISO name, native
+ * name, region and variant of the locale.
+ *
+ * @return Language[]
+ */
+ public static function getAvailableLocalesInfo();
+
+ /**
+ * Returns list of calendar formats for ISO formatting.
+ *
+ * @param string|null $locale current locale used if null
+ *
+ * @return array
+ */
+ public function getCalendarFormats($locale = null);
+
+ /**
+ * Get the days of the week
+ *
+ * @return array
+ */
+ public static function getDays();
+
+ /**
+ * Get the fallback locale.
+ *
+ * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
+ *
+ * @return string|null
+ */
+ public static function getFallbackLocale();
+
+ /**
+ * List of replacements from date() format to isoFormat().
+ *
+ * @return array
+ */
+ public static function getFormatsToIsoReplacements();
+
+ /**
+ * Return default humanDiff() options (merged flags as integer).
+ *
+ * @return int
+ */
+ public static function getHumanDiffOptions();
+
+ /**
+ * Returns list of locale formats for ISO formatting.
+ *
+ * @param string|null $locale current locale used if null
+ *
+ * @return array
+ */
+ public function getIsoFormats($locale = null);
+
+ /**
+ * Returns list of locale units for ISO formatting.
+ *
+ * @return array
+ */
+ public static function getIsoUnits();
+
+ /**
+ * {@inheritdoc}
+ */
+ #[ReturnTypeWillChange]
+ public static function getLastErrors();
+
+ /**
+ * Get the raw callable macro registered globally or locally for a given name.
+ *
+ * @param string $name
+ *
+ * @return callable|null
+ */
+ public function getLocalMacro($name);
+
+ /**
+ * Get the translator of the current instance or the default if none set.
+ *
+ * @return \Symfony\Component\Translation\TranslatorInterface
+ */
+ public function getLocalTranslator();
+
+ /**
+ * Get the current translator locale.
+ *
+ * @return string
+ */
+ public static function getLocale();
+
+ /**
+ * Get the raw callable macro registered globally for a given name.
+ *
+ * @param string $name
+ *
+ * @return callable|null
+ */
+ public static function getMacro($name);
+
+ /**
+ * get midday/noon hour
+ *
+ * @return int
+ */
+ public static function getMidDayAt();
+
+ /**
+ * Returns the offset hour and minute formatted with +/- and a given separator (":" by default).
+ * For example, if the time zone is 9 hours 30 minutes, you'll get "+09:30", with "@@" as first
+ * argument, "+09@@30", with "" as first argument, "+0930". Negative offset will return something
+ * like "-12:00".
+ *
+ * @param string $separator string to place between hours and minutes (":" by default)
+ *
+ * @return string
+ */
+ public function getOffsetString($separator = ':');
+
+ /**
+ * Returns a unit of the instance padded with 0 by default or any other string if specified.
+ *
+ * @param string $unit Carbon unit name
+ * @param int $length Length of the output (2 by default)
+ * @param string $padString String to use for padding ("0" by default)
+ * @param int $padType Side(s) to pad (STR_PAD_LEFT by default)
+ *
+ * @return string
+ */
+ public function getPaddedUnit($unit, $length = 2, $padString = '0', $padType = 0);
+
+ /**
+ * Returns a timestamp rounded with the given precision (6 by default).
+ *
+ * @example getPreciseTimestamp() 1532087464437474 (microsecond maximum precision)
+ * @example getPreciseTimestamp(6) 1532087464437474
+ * @example getPreciseTimestamp(5) 153208746443747 (1/100000 second precision)
+ * @example getPreciseTimestamp(4) 15320874644375 (1/10000 second precision)
+ * @example getPreciseTimestamp(3) 1532087464437 (millisecond precision)
+ * @example getPreciseTimestamp(2) 153208746444 (1/100 second precision)
+ * @example getPreciseTimestamp(1) 15320874644 (1/10 second precision)
+ * @example getPreciseTimestamp(0) 1532087464 (second precision)
+ * @example getPreciseTimestamp(-1) 153208746 (10 second precision)
+ * @example getPreciseTimestamp(-2) 15320875 (100 second precision)
+ *
+ * @param int $precision
+ *
+ * @return float
+ */
+ public function getPreciseTimestamp($precision = 6);
+
+ /**
+ * Returns current local settings.
+ *
+ * @return array
+ */
+ public function getSettings();
+
+ /**
+ * Get the Carbon instance (real or mock) to be returned when a "now"
+ * instance is created.
+ *
+ * @return Closure|static the current instance used for testing
+ */
+ public static function getTestNow();
+
+ /**
+ * Return a format from H:i to H:i:s.u according to given unit precision.
+ *
+ * @param string $unitPrecision "minute", "second", "millisecond" or "microsecond"
+ *
+ * @return string
+ */
+ public static function getTimeFormatByPrecision($unitPrecision);
+
+ /**
+ * Get the translation of the current week day name (with context for languages with multiple forms).
+ *
+ * @param string|null $context whole format string
+ * @param string $keySuffix "", "_short" or "_min"
+ * @param string|null $defaultValue default value if translation missing
+ *
+ * @return string
+ */
+ public function getTranslatedDayName($context = null, $keySuffix = '', $defaultValue = null);
+
+ /**
+ * Get the translation of the current abbreviated week day name (with context for languages with multiple forms).
+ *
+ * @param string|null $context whole format string
+ *
+ * @return string
+ */
+ public function getTranslatedMinDayName($context = null);
+
+ /**
+ * Get the translation of the current month day name (with context for languages with multiple forms).
+ *
+ * @param string|null $context whole format string
+ * @param string $keySuffix "" or "_short"
+ * @param string|null $defaultValue default value if translation missing
+ *
+ * @return string
+ */
+ public function getTranslatedMonthName($context = null, $keySuffix = '', $defaultValue = null);
+
+ /**
+ * Get the translation of the current short week day name (with context for languages with multiple forms).
+ *
+ * @param string|null $context whole format string
+ *
+ * @return string
+ */
+ public function getTranslatedShortDayName($context = null);
+
+ /**
+ * Get the translation of the current short month day name (with context for languages with multiple forms).
+ *
+ * @param string|null $context whole format string
+ *
+ * @return string
+ */
+ public function getTranslatedShortMonthName($context = null);
+
+ /**
+ * Returns raw translation message for a given key.
+ *
+ * @param string $key key to find
+ * @param string|null $locale current locale used if null
+ * @param string|null $default default value if translation returns the key
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator an optional translator to use
+ *
+ * @return string
+ */
+ public function getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null);
+
+ /**
+ * Returns raw translation message for a given key.
+ *
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator the translator to use
+ * @param string $key key to find
+ * @param string|null $locale current locale used if null
+ * @param string|null $default default value if translation returns the key
+ *
+ * @return string
+ */
+ public static function getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null);
+
+ /**
+ * Get the default translator instance in use.
+ *
+ * @return \Symfony\Component\Translation\TranslatorInterface
+ */
+ public static function getTranslator();
+
+ /**
+ * Get the last day of week
+ *
+ * @return int
+ */
+ public static function getWeekEndsAt();
+
+ /**
+ * Get the first day of week
+ *
+ * @return int
+ */
+ public static function getWeekStartsAt();
+
+ /**
+ * Get weekend days
+ *
+ * @return array
+ */
+ public static function getWeekendDays();
+
+ /**
+ * Determines if the instance is greater (after) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:15'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function greaterThan($date): bool;
+
+ /**
+ * Determines if the instance is greater (after) than or equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:15'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function greaterThanOrEqualTo($date): bool;
+
+ /**
+ * Determines if the instance is greater (after) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:15'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see greaterThan()
+ *
+ * @return bool
+ */
+ public function gt($date): bool;
+
+ /**
+ * Determines if the instance is greater (after) than or equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:15'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see greaterThanOrEqualTo()
+ *
+ * @return bool
+ */
+ public function gte($date): bool;
+
+ /**
+ * Checks if the (date)time string is in a given format.
+ *
+ * @example
+ * ```
+ * Carbon::hasFormat('11:12:45', 'h:i:s'); // true
+ * Carbon::hasFormat('13:12:45', 'h:i:s'); // false
+ * ```
+ *
+ * @param string $date
+ * @param string $format
+ *
+ * @return bool
+ */
+ public static function hasFormat($date, $format);
+
+ /**
+ * Checks if the (date)time string is in a given format.
+ *
+ * @example
+ * ```
+ * Carbon::hasFormatWithModifiers('31/08/2015', 'd#m#Y'); // true
+ * Carbon::hasFormatWithModifiers('31/08/2015', 'm#d#Y'); // false
+ * ```
+ *
+ * @param string $date
+ * @param string $format
+ *
+ * @return bool
+ */
+ public static function hasFormatWithModifiers($date, $format): bool;
+
+ /**
+ * Checks if macro is registered globally or locally.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function hasLocalMacro($name);
+
+ /**
+ * Return true if the current instance has its own translator.
+ *
+ * @return bool
+ */
+ public function hasLocalTranslator();
+
+ /**
+ * Checks if macro is registered globally.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public static function hasMacro($name);
+
+ /**
+ * Determine if a time string will produce a relative date.
+ *
+ * @param string $time
+ *
+ * @return bool true if time match a relative date, false if absolute or invalid time string
+ */
+ public static function hasRelativeKeywords($time);
+
+ /**
+ * Determine if there is a valid test instance set. A valid test instance
+ * is anything that is not null.
+ *
+ * @return bool true if there is a test instance, otherwise false
+ */
+ public static function hasTestNow();
+
+ /**
+ * Create a Carbon instance from a DateTime one.
+ *
+ * @param DateTimeInterface $date
+ *
+ * @return static
+ */
+ public static function instance($date);
+
+ /**
+ * Returns true if the current date matches the given string.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2018')); // false
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('06-02')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06-02')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('Sunday')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('June')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:45')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:00')); // false
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12h')); // true
+ * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3pm')); // true
+ * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3am')); // false
+ * ```
+ *
+ * @param string $tester day name, month name, hour, date, etc. as string
+ *
+ * @return bool
+ */
+ public function is(string $tester);
+
+ /**
+ * Determines if the instance is greater (after) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:15'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see greaterThan()
+ *
+ * @return bool
+ */
+ public function isAfter($date): bool;
+
+ /**
+ * Determines if the instance is less (before) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:15'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see lessThan()
+ *
+ * @return bool
+ */
+ public function isBefore($date): bool;
+
+ /**
+ * Determines if the instance is between two others
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25')->isBetween('2018-07-14', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->isBetween('2018-08-01', '2018-08-20'); // false
+ * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01', false); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ * @param bool $equal Indicates if an equal to comparison should be done
+ *
+ * @return bool
+ */
+ public function isBetween($date1, $date2, $equal = true): bool;
+
+ /**
+ * Check if its the birthday. Compares the date/month values of the two dates.
+ *
+ * @example
+ * ```
+ * Carbon::now()->subYears(5)->isBirthday(); // true
+ * Carbon::now()->subYears(5)->subDay()->isBirthday(); // false
+ * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-05')); // true
+ * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-06')); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
+ *
+ * @return bool
+ */
+ public function isBirthday($date = null);
+
+ /**
+ * Determines if the instance is in the current unit given.
+ *
+ * @example
+ * ```
+ * Carbon::now()->isCurrentUnit('hour'); // true
+ * Carbon::now()->subHours(2)->isCurrentUnit('hour'); // false
+ * ```
+ *
+ * @param string $unit The unit to test.
+ *
+ * @throws BadMethodCallException
+ *
+ * @return bool
+ */
+ public function isCurrentUnit($unit);
+
+ /**
+ * Checks if this day is a specific day of the week.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::WEDNESDAY); // true
+ * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::FRIDAY); // false
+ * Carbon::parse('2019-07-17')->isDayOfWeek('Wednesday'); // true
+ * Carbon::parse('2019-07-17')->isDayOfWeek('Friday'); // false
+ * ```
+ *
+ * @param int $dayOfWeek
+ *
+ * @return bool
+ */
+ public function isDayOfWeek($dayOfWeek);
+
+ /**
+ * Check if the instance is end of day.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(); // true
+ * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(); // true
+ * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(); // true
+ * Carbon::parse('2019-02-28 23:59:58.999999')->isEndOfDay(); // false
+ * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(true); // true
+ * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(true); // false
+ * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(true); // false
+ * ```
+ *
+ * @param bool $checkMicroseconds check time at microseconds precision
+ *
+ * @return bool
+ */
+ public function isEndOfDay($checkMicroseconds = false);
+
+ /**
+ * Returns true if the date was created using CarbonImmutable::endOfTime()
+ *
+ * @return bool
+ */
+ public function isEndOfTime(): bool;
+
+ /**
+ * Determines if the instance is in the future, ie. greater (after) than now.
+ *
+ * @example
+ * ```
+ * Carbon::now()->addHours(5)->isFuture(); // true
+ * Carbon::now()->subHours(5)->isFuture(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isFuture();
+
+ /**
+ * Returns true if the current class/instance is immutable.
+ *
+ * @return bool
+ */
+ public static function isImmutable();
+
+ /**
+ * Check if today is the last day of the Month
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-02-28')->isLastOfMonth(); // true
+ * Carbon::parse('2019-03-28')->isLastOfMonth(); // false
+ * Carbon::parse('2019-03-30')->isLastOfMonth(); // false
+ * Carbon::parse('2019-03-31')->isLastOfMonth(); // true
+ * Carbon::parse('2019-04-30')->isLastOfMonth(); // true
+ * ```
+ *
+ * @return bool
+ */
+ public function isLastOfMonth();
+
+ /**
+ * Determines if the instance is a leap year.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2020-01-01')->isLeapYear(); // true
+ * Carbon::parse('2019-01-01')->isLeapYear(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isLeapYear();
+
+ /**
+ * Determines if the instance is a long year
+ *
+ * @example
+ * ```
+ * Carbon::parse('2015-01-01')->isLongYear(); // true
+ * Carbon::parse('2016-01-01')->isLongYear(); // false
+ * ```
+ *
+ * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
+ *
+ * @return bool
+ */
+ public function isLongYear();
+
+ /**
+ * Check if the instance is midday.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-02-28 11:59:59.999999')->isMidday(); // false
+ * Carbon::parse('2019-02-28 12:00:00')->isMidday(); // true
+ * Carbon::parse('2019-02-28 12:00:00.999999')->isMidday(); // true
+ * Carbon::parse('2019-02-28 12:00:01')->isMidday(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isMidday();
+
+ /**
+ * Check if the instance is start of day / midnight.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-02-28 00:00:00')->isMidnight(); // true
+ * Carbon::parse('2019-02-28 00:00:00.999999')->isMidnight(); // true
+ * Carbon::parse('2019-02-28 00:00:01')->isMidnight(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isMidnight();
+
+ /**
+ * Returns true if a property can be changed via setter.
+ *
+ * @param string $unit
+ *
+ * @return bool
+ */
+ public static function isModifiableUnit($unit);
+
+ /**
+ * Returns true if the current class/instance is mutable.
+ *
+ * @return bool
+ */
+ public static function isMutable();
+
+ /**
+ * Determines if the instance is in the past, ie. less (before) than now.
+ *
+ * @example
+ * ```
+ * Carbon::now()->subHours(5)->isPast(); // true
+ * Carbon::now()->addHours(5)->isPast(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isPast();
+
+ /**
+ * Compares the formatted values of the two dates.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-12-13')); // true
+ * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-06-14')); // false
+ * ```
+ *
+ * @param string $format date formats to compare.
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date instance to compare with or null to use current day.
+ *
+ * @return bool
+ */
+ public function isSameAs($format, $date = null);
+
+ /**
+ * Checks if the passed in date is in the same month as the instance´s month.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-01-01')); // true
+ * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-02-01')); // false
+ * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01')); // false
+ * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01'), false); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ * @param bool $ofSameYear Check if it is the same month in the same year.
+ *
+ * @return bool
+ */
+ public function isSameMonth($date = null, $ofSameYear = true);
+
+ /**
+ * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed).
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-03-01')); // true
+ * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-04-01')); // false
+ * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01')); // false
+ * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01'), false); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date The instance to compare with or null to use current day.
+ * @param bool $ofSameYear Check if it is the same month in the same year.
+ *
+ * @return bool
+ */
+ public function isSameQuarter($date = null, $ofSameYear = true);
+
+ /**
+ * Determines if the instance is in the current unit given.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-01-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // true
+ * Carbon::parse('2018-12-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // false
+ * ```
+ *
+ * @param string $unit singular unit string
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date instance to compare with or null to use current day.
+ *
+ * @throws BadComparisonUnitException
+ *
+ * @return bool
+ */
+ public function isSameUnit($unit, $date = null);
+
+ /**
+ * Check if the instance is start of day / midnight.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-02-28 00:00:00')->isStartOfDay(); // true
+ * Carbon::parse('2019-02-28 00:00:00.999999')->isStartOfDay(); // true
+ * Carbon::parse('2019-02-28 00:00:01')->isStartOfDay(); // false
+ * Carbon::parse('2019-02-28 00:00:00.000000')->isStartOfDay(true); // true
+ * Carbon::parse('2019-02-28 00:00:00.000012')->isStartOfDay(true); // false
+ * ```
+ *
+ * @param bool $checkMicroseconds check time at microseconds precision
+ *
+ * @return bool
+ */
+ public function isStartOfDay($checkMicroseconds = false);
+
+ /**
+ * Returns true if the date was created using CarbonImmutable::startOfTime()
+ *
+ * @return bool
+ */
+ public function isStartOfTime(): bool;
+
+ /**
+ * Returns true if the strict mode is globally in use, false else.
+ * (It can be overridden in specific instances.)
+ *
+ * @return bool
+ */
+ public static function isStrictModeEnabled();
+
+ /**
+ * Determines if the instance is today.
+ *
+ * @example
+ * ```
+ * Carbon::today()->isToday(); // true
+ * Carbon::tomorrow()->isToday(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isToday();
+
+ /**
+ * Determines if the instance is tomorrow.
+ *
+ * @example
+ * ```
+ * Carbon::tomorrow()->isTomorrow(); // true
+ * Carbon::yesterday()->isTomorrow(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isTomorrow();
+
+ /**
+ * Determines if the instance is a weekday.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-07-14')->isWeekday(); // false
+ * Carbon::parse('2019-07-15')->isWeekday(); // true
+ * ```
+ *
+ * @return bool
+ */
+ public function isWeekday();
+
+ /**
+ * Determines if the instance is a weekend day.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-07-14')->isWeekend(); // true
+ * Carbon::parse('2019-07-15')->isWeekend(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isWeekend();
+
+ /**
+ * Determines if the instance is yesterday.
+ *
+ * @example
+ * ```
+ * Carbon::yesterday()->isYesterday(); // true
+ * Carbon::tomorrow()->isYesterday(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isYesterday();
+
+ /**
+ * Format in the current language using ISO replacement patterns.
+ *
+ * @param string $format
+ * @param string|null $originalFormat provide context if a chunk has been passed alone
+ *
+ * @return string
+ */
+ public function isoFormat(string $format, ?string $originalFormat = null): string;
+
+ /**
+ * Get/set the week number using given first day of week and first
+ * day of year included in the first week. Or use ISO format if no settings
+ * given.
+ *
+ * @param int|null $week
+ * @param int|null $dayOfWeek
+ * @param int|null $dayOfYear
+ *
+ * @return int|static
+ */
+ public function isoWeek($week = null, $dayOfWeek = null, $dayOfYear = null);
+
+ /**
+ * Set/get the week number of year using given first day of week and first
+ * day of year included in the first week. Or use ISO format if no settings
+ * given.
+ *
+ * @param int|null $year if null, act as a getter, if not null, set the year and return current instance.
+ * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
+ * @param int|null $dayOfYear first day of year included in the week #1
+ *
+ * @return int|static
+ */
+ public function isoWeekYear($year = null, $dayOfWeek = null, $dayOfYear = null);
+
+ /**
+ * Get/set the ISO weekday from 1 (Monday) to 7 (Sunday).
+ *
+ * @param int|null $value new value for weekday if using as setter.
+ *
+ * @return static|int
+ */
+ public function isoWeekday($value = null);
+
+ /**
+ * Get the number of weeks of the current week-year using given first day of week and first
+ * day of year included in the first week. Or use ISO format if no settings
+ * given.
+ *
+ * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
+ * @param int|null $dayOfYear first day of year included in the week #1
+ *
+ * @return int
+ */
+ public function isoWeeksInYear($dayOfWeek = null, $dayOfYear = null);
+
+ /**
+ * Prepare the object for JSON serialization.
+ *
+ * @return array|string
+ */
+ #[ReturnTypeWillChange]
+ public function jsonSerialize();
+
+ /**
+ * Modify to the last occurrence of a given day of the week
+ * in the current month. If no dayOfWeek is provided, modify to the
+ * last day of the current month. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek
+ *
+ * @return static
+ */
+ public function lastOfMonth($dayOfWeek = null);
+
+ /**
+ * Modify to the last occurrence of a given day of the week
+ * in the current quarter. If no dayOfWeek is provided, modify to the
+ * last day of the current quarter. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function lastOfQuarter($dayOfWeek = null);
+
+ /**
+ * Modify to the last occurrence of a given day of the week
+ * in the current year. If no dayOfWeek is provided, modify to the
+ * last day of the current year. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function lastOfYear($dayOfWeek = null);
+
+ /**
+ * Determines if the instance is less (before) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:15'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function lessThan($date): bool;
+
+ /**
+ * Determines if the instance is less (before) or equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:15'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function lessThanOrEqualTo($date): bool;
+
+ /**
+ * Get/set the locale for the current instance.
+ *
+ * @param string|null $locale
+ * @param string ...$fallbackLocales
+ *
+ * @return $this|string
+ */
+ public function locale(?string $locale = null, ...$fallbackLocales);
+
+ /**
+ * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
+ * Support is considered enabled if the 3 words are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasDiffOneDayWords($locale);
+
+ /**
+ * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
+ * Support is considered enabled if the 4 sentences are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasDiffSyntax($locale);
+
+ /**
+ * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
+ * Support is considered enabled if the 2 words are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasDiffTwoDayWords($locale);
+
+ /**
+ * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
+ * Support is considered enabled if the 4 sentences are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasPeriodSyntax($locale);
+
+ /**
+ * Returns true if the given locale is internally supported and has short-units support.
+ * Support is considered enabled if either year, day or hour has a short variant translated.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasShortUnits($locale);
+
+ /**
+ * Determines if the instance is less (before) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:15'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see lessThan()
+ *
+ * @return bool
+ */
+ public function lt($date): bool;
+
+ /**
+ * Determines if the instance is less (before) or equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:15'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see lessThanOrEqualTo()
+ *
+ * @return bool
+ */
+ public function lte($date): bool;
+
+ /**
+ * Register a custom macro.
+ *
+ * @example
+ * ```
+ * $userSettings = [
+ * 'locale' => 'pt',
+ * 'timezone' => 'America/Sao_Paulo',
+ * ];
+ * Carbon::macro('userFormat', function () use ($userSettings) {
+ * return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar();
+ * });
+ * echo Carbon::yesterday()->hours(11)->userFormat();
+ * ```
+ *
+ * @param string $name
+ * @param object|callable $macro
+ *
+ * @return void
+ */
+ public static function macro($name, $macro);
+
+ /**
+ * Make a Carbon instance from given variable if possible.
+ *
+ * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
+ * and recurrences). Throw an exception for invalid format, but otherwise return null.
+ *
+ * @param mixed $var
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|null
+ */
+ public static function make($var);
+
+ /**
+ * Get the maximum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return static
+ */
+ public function max($date = null);
+
+ /**
+ * Create a Carbon instance for the greatest supported date.
+ *
+ * @return static
+ */
+ public static function maxValue();
+
+ /**
+ * Get the maximum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see max()
+ *
+ * @return static
+ */
+ public function maximum($date = null);
+
+ /**
+ * Return the meridiem of the current time in the current locale.
+ *
+ * @param bool $isLower if true, returns lowercase variant if available in the current locale.
+ *
+ * @return string
+ */
+ public function meridiem(bool $isLower = false): string;
+
+ /**
+ * Modify to midday, default to self::$midDayAt
+ *
+ * @return static
+ */
+ public function midDay();
+
+ /**
+ * Get the minimum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return static
+ */
+ public function min($date = null);
+
+ /**
+ * Create a Carbon instance for the lowest supported date.
+ *
+ * @return static
+ */
+ public static function minValue();
+
+ /**
+ * Get the minimum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see min()
+ *
+ * @return static
+ */
+ public function minimum($date = null);
+
+ /**
+ * Mix another object into the class.
+ *
+ * @example
+ * ```
+ * Carbon::mixin(new class {
+ * public function addMoon() {
+ * return function () {
+ * return $this->addDays(30);
+ * };
+ * }
+ * public function subMoon() {
+ * return function () {
+ * return $this->subDays(30);
+ * };
+ * }
+ * });
+ * $fullMoon = Carbon::create('2018-12-22');
+ * $nextFullMoon = $fullMoon->addMoon();
+ * $blackMoon = Carbon::create('2019-01-06');
+ * $previousBlackMoon = $blackMoon->subMoon();
+ * echo "$nextFullMoon\n";
+ * echo "$previousBlackMoon\n";
+ * ```
+ *
+ * @param object|string $mixin
+ *
+ * @throws ReflectionException
+ *
+ * @return void
+ */
+ public static function mixin($mixin);
+
+ /**
+ * Calls \DateTime::modify if mutable or \DateTimeImmutable::modify else.
+ *
+ * @see https://php.net/manual/en/datetime.modify.php
+ */
+ #[ReturnTypeWillChange]
+ public function modify($modify);
+
+ /**
+ * Determines if the instance is not equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->ne(Carbon::parse('2018-07-25 12:45:16')); // false
+ * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see notEqualTo()
+ *
+ * @return bool
+ */
+ public function ne($date): bool;
+
+ /**
+ * Modify to the next occurrence of a given modifier such as a day of
+ * the week. If no modifier is provided, modify to the next occurrence
+ * of the current day of the week. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param string|int|null $modifier
+ *
+ * @return static
+ */
+ public function next($modifier = null);
+
+ /**
+ * Go forward to the next weekday.
+ *
+ * @return static
+ */
+ public function nextWeekday();
+
+ /**
+ * Go forward to the next weekend day.
+ *
+ * @return static
+ */
+ public function nextWeekendDay();
+
+ /**
+ * Determines if the instance is not equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->notEqualTo(Carbon::parse('2018-07-25 12:45:16')); // false
+ * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function notEqualTo($date): bool;
+
+ /**
+ * Get a Carbon instance for the current date and time.
+ *
+ * @param DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function now($tz = null);
+
+ /**
+ * Returns a present instance in the same timezone.
+ *
+ * @return static
+ */
+ public function nowWithSameTz();
+
+ /**
+ * Modify to the given occurrence of a given day of the week
+ * in the current month. If the calculated occurrence is outside the scope
+ * of the current month, then return false and no modifications are made.
+ * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int $nth
+ * @param int $dayOfWeek
+ *
+ * @return mixed
+ */
+ public function nthOfMonth($nth, $dayOfWeek);
+
+ /**
+ * Modify to the given occurrence of a given day of the week
+ * in the current quarter. If the calculated occurrence is outside the scope
+ * of the current quarter, then return false and no modifications are made.
+ * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int $nth
+ * @param int $dayOfWeek
+ *
+ * @return mixed
+ */
+ public function nthOfQuarter($nth, $dayOfWeek);
+
+ /**
+ * Modify to the given occurrence of a given day of the week
+ * in the current year. If the calculated occurrence is outside the scope
+ * of the current year, then return false and no modifications are made.
+ * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int $nth
+ * @param int $dayOfWeek
+ *
+ * @return mixed
+ */
+ public function nthOfYear($nth, $dayOfWeek);
+
+ /**
+ * Return a property with its ordinal.
+ *
+ * @param string $key
+ * @param string|null $period
+ *
+ * @return string
+ */
+ public function ordinal(string $key, ?string $period = null): string;
+
+ /**
+ * Create a carbon instance from a string.
+ *
+ * This is an alias for the constructor that allows better fluent syntax
+ * as it allows you to do Carbon::parse('Monday next week')->fn() rather
+ * than (new Carbon('Monday next week'))->fn().
+ *
+ * @param string|DateTimeInterface|null $time
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function parse($time = null, $tz = null);
+
+ /**
+ * Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
+ *
+ * @param string $time date/time string in the given language (may also contain English).
+ * @param string|null $locale if locale is null or not specified, current global locale will be
+ * used instead.
+ * @param DateTimeZone|string|null $tz optional timezone for the new instance.
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function parseFromLocale($time, $locale = null, $tz = null);
+
+ /**
+ * Returns standardized plural of a given singular/plural unit name (in English).
+ *
+ * @param string $unit
+ *
+ * @return string
+ */
+ public static function pluralUnit(string $unit): string;
+
+ /**
+ * Modify to the previous occurrence of a given modifier such as a day of
+ * the week. If no dayOfWeek is provided, modify to the previous occurrence
+ * of the current day of the week. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param string|int|null $modifier
+ *
+ * @return static
+ */
+ public function previous($modifier = null);
+
+ /**
+ * Go backward to the previous weekday.
+ *
+ * @return static
+ */
+ public function previousWeekday();
+
+ /**
+ * Go backward to the previous weekend day.
+ *
+ * @return static
+ */
+ public function previousWeekendDay();
+
+ /**
+ * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval).
+ *
+ * @param \DateTimeInterface|Carbon|CarbonImmutable|null $end period end date
+ * @param int|\DateInterval|string|null $interval period default interval or number of the given $unit
+ * @param string|null $unit if specified, $interval must be an integer
+ *
+ * @return CarbonPeriod
+ */
+ public function range($end = null, $interval = null, $unit = null);
+
+ /**
+ * Call native PHP DateTime/DateTimeImmutable add() method.
+ *
+ * @param DateInterval $interval
+ *
+ * @return static
+ */
+ public function rawAdd(DateInterval $interval);
+
+ /**
+ * Create a Carbon instance from a specific format.
+ *
+ * @param string $format Datetime format
+ * @param string $time
+ * @param DateTimeZone|string|false|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ public static function rawCreateFromFormat($format, $time, $tz = null);
+
+ /**
+ * @see https://php.net/manual/en/datetime.format.php
+ *
+ * @param string $format
+ *
+ * @return string
+ */
+ public function rawFormat($format);
+
+ /**
+ * Create a carbon instance from a string.
+ *
+ * This is an alias for the constructor that allows better fluent syntax
+ * as it allows you to do Carbon::parse('Monday next week')->fn() rather
+ * than (new Carbon('Monday next week'))->fn().
+ *
+ * @param string|DateTimeInterface|null $time
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function rawParse($time = null, $tz = null);
+
+ /**
+ * Call native PHP DateTime/DateTimeImmutable sub() method.
+ *
+ * @param DateInterval $interval
+ *
+ * @return static
+ */
+ public function rawSub(DateInterval $interval);
+
+ /**
+ * Remove all macros and generic macros.
+ */
+ public static function resetMacros();
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @see settings
+ *
+ * Reset the month overflow behavior.
+ *
+ * @return void
+ */
+ public static function resetMonthsOverflow();
+
+ /**
+ * Reset the format used to the default when type juggling a Carbon instance to a string
+ *
+ * @return void
+ */
+ public static function resetToStringFormat();
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @see settings
+ *
+ * Reset the month overflow behavior.
+ *
+ * @return void
+ */
+ public static function resetYearsOverflow();
+
+ /**
+ * Round the current instance second with given precision if specified.
+ *
+ * @param float|int|string|\DateInterval|null $precision
+ * @param string $function
+ *
+ * @return CarbonInterface
+ */
+ public function round($precision = 1, $function = 'round');
+
+ /**
+ * Round the current instance at the given unit with given precision if specified and the given function.
+ *
+ * @param string $unit
+ * @param float|int $precision
+ * @param string $function
+ *
+ * @return CarbonInterface
+ */
+ public function roundUnit($unit, $precision = 1, $function = 'round');
+
+ /**
+ * Round the current instance week.
+ *
+ * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
+ *
+ * @return CarbonInterface
+ */
+ public function roundWeek($weekStartsAt = null);
+
+ /**
+ * The number of seconds since midnight.
+ *
+ * @return int
+ */
+ public function secondsSinceMidnight();
+
+ /**
+ * The number of seconds until 23:59:59.
+ *
+ * @return int
+ */
+ public function secondsUntilEndOfDay();
+
+ /**
+ * Return a serialized string of the instance.
+ *
+ * @return string
+ */
+ public function serialize();
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather transform Carbon object before the serialization.
+ *
+ * JSON serialize all Carbon instances using the given callback.
+ *
+ * @param callable $callback
+ *
+ * @return void
+ */
+ public static function serializeUsing($callback);
+
+ /**
+ * Set a part of the Carbon object
+ *
+ * @param string|array $name
+ * @param string|int|DateTimeZone $value
+ *
+ * @throws ImmutableException|UnknownSetterException
+ *
+ * @return $this
+ */
+ public function set($name, $value = null);
+
+ /**
+ * Set the date with gregorian year, month and day numbers.
+ *
+ * @see https://php.net/manual/en/datetime.setdate.php
+ *
+ * @param int $year
+ * @param int $month
+ * @param int $day
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function setDate($year, $month, $day);
+
+ /**
+ * Set the year, month, and date for this instance to that of the passed instance.
+ *
+ * @param Carbon|DateTimeInterface $date now if null
+ *
+ * @return static
+ */
+ public function setDateFrom($date = null);
+
+ /**
+ * Set the date and time all together.
+ *
+ * @param int $year
+ * @param int $month
+ * @param int $day
+ * @param int $hour
+ * @param int $minute
+ * @param int $second
+ * @param int $microseconds
+ *
+ * @return static
+ */
+ public function setDateTime($year, $month, $day, $hour, $minute, $second = 0, $microseconds = 0);
+
+ /**
+ * Set the date and time for this instance to that of the passed instance.
+ *
+ * @param Carbon|DateTimeInterface $date
+ *
+ * @return static
+ */
+ public function setDateTimeFrom($date = null);
+
+ /**
+ * Set the fallback locale.
+ *
+ * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
+ *
+ * @param string $locale
+ */
+ public static function setFallbackLocale($locale);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @see settings
+ *
+ * @param int $humanDiffOptions
+ */
+ public static function setHumanDiffOptions($humanDiffOptions);
+
+ /**
+ * Set a date according to the ISO 8601 standard - using weeks and day offsets rather than specific dates.
+ *
+ * @see https://php.net/manual/en/datetime.setisodate.php
+ *
+ * @param int $year
+ * @param int $week
+ * @param int $day
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function setISODate($year, $week, $day = 1);
+
+ /**
+ * Set the translator for the current instance.
+ *
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator
+ *
+ * @return $this
+ */
+ public function setLocalTranslator(\Symfony\Component\Translation\TranslatorInterface $translator);
+
+ /**
+ * Set the current translator locale and indicate if the source locale file exists.
+ * Pass 'auto' as locale to use closest language from the current LC_TIME locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function setLocale($locale);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather consider mid-day is always 12pm, then if you need to test if it's an other
+ * hour, test it explicitly:
+ * $date->format('G') == 13
+ * or to set explicitly to a given hour:
+ * $date->setTime(13, 0, 0, 0)
+ *
+ * Set midday/noon hour
+ *
+ * @param int $hour midday hour
+ *
+ * @return void
+ */
+ public static function setMidDayAt($hour);
+
+ /**
+ * Set a Carbon instance (real or mock) to be returned when a "now"
+ * instance is created. The provided instance will be returned
+ * specifically under the following conditions:
+ * - A call to the static now() method, ex. Carbon::now()
+ * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
+ * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
+ * - When a string containing the desired time is passed to Carbon::parse().
+ *
+ * Note the timezone parameter was left out of the examples above and
+ * has no affect as the mock value will be returned regardless of its value.
+ *
+ * To clear the test instance call this method using the default
+ * parameter of null.
+ *
+ * /!\ Use this method for unit tests only.
+ *
+ * @param Closure|static|string|false|null $testNow real or mock Carbon instance
+ */
+ public static function setTestNow($testNow = null);
+
+ /**
+ * Resets the current time of the DateTime object to a different time.
+ *
+ * @see https://php.net/manual/en/datetime.settime.php
+ *
+ * @param int $hour
+ * @param int $minute
+ * @param int $second
+ * @param int $microseconds
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function setTime($hour, $minute, $second = 0, $microseconds = 0);
+
+ /**
+ * Set the hour, minute, second and microseconds for this instance to that of the passed instance.
+ *
+ * @param Carbon|DateTimeInterface $date now if null
+ *
+ * @return static
+ */
+ public function setTimeFrom($date = null);
+
+ /**
+ * Set the time by time string.
+ *
+ * @param string $time
+ *
+ * @return static
+ */
+ public function setTimeFromTimeString($time);
+
+ /**
+ * Set the instance's timestamp.
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $unixTimestamp
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function setTimestamp($unixTimestamp);
+
+ /**
+ * Set the instance's timezone from a string or object.
+ *
+ * @param DateTimeZone|string $value
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function setTimezone($value);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather let Carbon object being casted to string with DEFAULT_TO_STRING_FORMAT, and
+ * use other method or custom format passed to format() method if you need to dump an other string
+ * format.
+ *
+ * Set the default format used when type juggling a Carbon instance to a string
+ *
+ * @param string|Closure|null $format
+ *
+ * @return void
+ */
+ public static function setToStringFormat($format);
+
+ /**
+ * Set the default translator instance to use.
+ *
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator
+ *
+ * @return void
+ */
+ public static function setTranslator(\Symfony\Component\Translation\TranslatorInterface $translator);
+
+ /**
+ * Set specified unit to new given value.
+ *
+ * @param string $unit year, month, day, hour, minute, second or microsecond
+ * @param int $value new value for given unit
+ *
+ * @return static
+ */
+ public function setUnit($unit, $value = null);
+
+ /**
+ * Set any unit to a new value without overflowing current other unit given.
+ *
+ * @param string $valueUnit unit name to modify
+ * @param int $value new value for the input unit
+ * @param string $overflowUnit unit name to not overflow
+ *
+ * @return static
+ */
+ public function setUnitNoOverflow($valueUnit, $value, $overflowUnit);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use UTF-8 language packages on every machine.
+ *
+ * Set if UTF8 will be used for localized date/time.
+ *
+ * @param bool $utf8
+ */
+ public static function setUtf8($utf8);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek
+ * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the
+ * start of week according to current locale selected and implicitly the end of week.
+ *
+ * Set the last day of week
+ *
+ * @param int|string $day week end day (or 'auto' to get the day before the first day of week
+ * from Carbon::getLocale() culture).
+ *
+ * @return void
+ */
+ public static function setWeekEndsAt($day);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the
+ * 'first_day_of_week' locale setting to change the start of week according to current locale
+ * selected and implicitly the end of week.
+ *
+ * Set the first day of week
+ *
+ * @param int|string $day week start day (or 'auto' to get the first day of week from Carbon::getLocale() culture).
+ *
+ * @return void
+ */
+ public static function setWeekStartsAt($day);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather consider week-end is always saturday and sunday, and if you have some custom
+ * week-end days to handle, give to those days an other name and create a macro for them:
+ *
+ * ```
+ * Carbon::macro('isDayOff', function ($date) {
+ * return $date->isSunday() || $date->isMonday();
+ * });
+ * Carbon::macro('isNotDayOff', function ($date) {
+ * return !$date->isDayOff();
+ * });
+ * if ($someDate->isDayOff()) ...
+ * if ($someDate->isNotDayOff()) ...
+ * // Add 5 not-off days
+ * $count = 5;
+ * while ($someDate->isDayOff() || ($count-- > 0)) {
+ * $someDate->addDay();
+ * }
+ * ```
+ *
+ * Set weekend days
+ *
+ * @param array $days
+ *
+ * @return void
+ */
+ public static function setWeekendDays($days);
+
+ /**
+ * Set specific options.
+ * - strictMode: true|false|null
+ * - monthOverflow: true|false|null
+ * - yearOverflow: true|false|null
+ * - humanDiffOptions: int|null
+ * - toStringFormat: string|Closure|null
+ * - toJsonFormat: string|Closure|null
+ * - locale: string|null
+ * - timezone: \DateTimeZone|string|int|null
+ * - macros: array|null
+ * - genericMacros: array|null
+ *
+ * @param array $settings
+ *
+ * @return $this|static
+ */
+ public function settings(array $settings);
+
+ /**
+ * Set the instance's timezone from a string or object and add/subtract the offset difference.
+ *
+ * @param DateTimeZone|string $value
+ *
+ * @return static
+ */
+ public function shiftTimezone($value);
+
+ /**
+ * Get the month overflow global behavior (can be overridden in specific instances).
+ *
+ * @return bool
+ */
+ public static function shouldOverflowMonths();
+
+ /**
+ * Get the month overflow global behavior (can be overridden in specific instances).
+ *
+ * @return bool
+ */
+ public static function shouldOverflowYears();
+
+ /**
+ * @alias diffForHumans
+ *
+ * Get the difference in a human readable format in the current locale from current instance to an other
+ * instance given (or now if null given).
+ */
+ public function since($other = null, $syntax = null, $short = false, $parts = 1, $options = null);
+
+ /**
+ * Returns standardized singular of a given singular/plural unit name (in English).
+ *
+ * @param string $unit
+ *
+ * @return string
+ */
+ public static function singularUnit(string $unit): string;
+
+ /**
+ * Modify to start of current given unit.
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16.334455')
+ * ->startOf('month')
+ * ->endOf('week', Carbon::FRIDAY);
+ * ```
+ *
+ * @param string $unit
+ * @param array<int, mixed> $params
+ *
+ * @return static
+ */
+ public function startOf($unit, ...$params);
+
+ /**
+ * Resets the date to the first day of the century and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfCentury();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfCentury();
+
+ /**
+ * Resets the time to 00:00:00 start of day
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfDay();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfDay();
+
+ /**
+ * Resets the date to the first day of the decade and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfDecade();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfDecade();
+
+ /**
+ * Modify to start of current hour, minutes and seconds become 0
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfHour();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfHour();
+
+ /**
+ * Resets the date to the first day of the millennium and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfMillennium();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfMillennium();
+
+ /**
+ * Modify to start of current minute, seconds become 0
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfMinute();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfMinute();
+
+ /**
+ * Resets the date to the first day of the month and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfMonth();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfMonth();
+
+ /**
+ * Resets the date to the first day of the quarter and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfQuarter();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfQuarter();
+
+ /**
+ * Modify to start of current second, microseconds become 0
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16.334455')
+ * ->startOfSecond()
+ * ->format('H:i:s.u');
+ * ```
+ *
+ * @return static
+ */
+ public function startOfSecond();
+
+ /**
+ * Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek() . "\n";
+ * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->startOfWeek() . "\n";
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek(Carbon::SUNDAY) . "\n";
+ * ```
+ *
+ * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
+ *
+ * @return static
+ */
+ public function startOfWeek($weekStartsAt = null);
+
+ /**
+ * Resets the date to the first day of the year and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfYear();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfYear();
+
+ /**
+ * Subtract given units or interval to the current instance.
+ *
+ * @example $date->sub('hour', 3)
+ * @example $date->sub(15, 'days')
+ * @example $date->sub(CarbonInterval::days(4))
+ *
+ * @param string|DateInterval|Closure|CarbonConverterInterface $unit
+ * @param int $value
+ * @param bool|null $overflow
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function sub($unit, $value = 1, $overflow = null);
+
+ public function subRealUnit($unit, $value = 1);
+
+ /**
+ * Subtract given units to the current instance.
+ *
+ * @param string $unit
+ * @param int $value
+ * @param bool|null $overflow
+ *
+ * @return static
+ */
+ public function subUnit($unit, $value = 1, $overflow = null);
+
+ /**
+ * Subtract any unit to a new value without overflowing current other unit given.
+ *
+ * @param string $valueUnit unit name to modify
+ * @param int $value amount to subtract to the input unit
+ * @param string $overflowUnit unit name to not overflow
+ *
+ * @return static
+ */
+ public function subUnitNoOverflow($valueUnit, $value, $overflowUnit);
+
+ /**
+ * Subtract given units or interval to the current instance.
+ *
+ * @see sub()
+ *
+ * @param string|DateInterval $unit
+ * @param int $value
+ * @param bool|null $overflow
+ *
+ * @return static
+ */
+ public function subtract($unit, $value = 1, $overflow = null);
+
+ /**
+ * Get the difference in a human readable format in the current locale from current instance to an other
+ * instance given (or now if null given).
+ *
+ * @return string
+ */
+ public function timespan($other = null, $timezone = null);
+
+ /**
+ * Set the instance's timestamp.
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $unixTimestamp
+ *
+ * @return static
+ */
+ public function timestamp($unixTimestamp);
+
+ /**
+ * @alias setTimezone
+ *
+ * @param DateTimeZone|string $value
+ *
+ * @return static
+ */
+ public function timezone($value);
+
+ /**
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given (or now if null given) to current instance.
+ *
+ * When comparing a value in the past to default now:
+ * 1 hour from now
+ * 5 months from now
+ *
+ * When comparing a value in the future to default now:
+ * 1 hour ago
+ * 5 months ago
+ *
+ * When comparing a value in the past to another value:
+ * 1 hour after
+ * 5 months after
+ *
+ * When comparing a value in the future to another value:
+ * 1 hour before
+ * 5 months before
+ *
+ * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
+ * if null passed, now will be used as comparison reference;
+ * if any other type, it will be converted to date and used as reference.
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * - 'other' entry (see above)
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single unit)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function to($other = null, $syntax = null, $short = false, $parts = 1, $options = null);
+
+ /**
+ * Get default array representation.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toArray());
+ * ```
+ *
+ * @return array
+ */
+ public function toArray();
+
+ /**
+ * Format the instance as ATOM
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toAtomString();
+ * ```
+ *
+ * @return string
+ */
+ public function toAtomString();
+
+ /**
+ * Format the instance as COOKIE
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toCookieString();
+ * ```
+ *
+ * @return string
+ */
+ public function toCookieString();
+
+ /**
+ * @alias toDateTime
+ *
+ * Return native DateTime PHP object matching the current instance.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toDate());
+ * ```
+ *
+ * @return DateTime
+ */
+ public function toDate();
+
+ /**
+ * Format the instance as date
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toDateString();
+ * ```
+ *
+ * @return string
+ */
+ public function toDateString();
+
+ /**
+ * Return native DateTime PHP object matching the current instance.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toDateTime());
+ * ```
+ *
+ * @return DateTime
+ */
+ public function toDateTime();
+
+ /**
+ * Return native toDateTimeImmutable PHP object matching the current instance.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toDateTimeImmutable());
+ * ```
+ *
+ * @return DateTimeImmutable
+ */
+ public function toDateTimeImmutable();
+
+ /**
+ * Format the instance as date and time T-separated with no timezone
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toDateTimeLocalString();
+ * echo "\n";
+ * echo Carbon::now()->toDateTimeLocalString('minute'); // You can specify precision among: minute, second, millisecond and microsecond
+ * ```
+ *
+ * @param string $unitPrecision
+ *
+ * @return string
+ */
+ public function toDateTimeLocalString($unitPrecision = 'second');
+
+ /**
+ * Format the instance as date and time
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toDateTimeString();
+ * ```
+ *
+ * @param string $unitPrecision
+ *
+ * @return string
+ */
+ public function toDateTimeString($unitPrecision = 'second');
+
+ /**
+ * Format the instance with day, date and time
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toDayDateTimeString();
+ * ```
+ *
+ * @return string
+ */
+ public function toDayDateTimeString();
+
+ /**
+ * Format the instance as a readable date
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toFormattedDateString();
+ * ```
+ *
+ * @return string
+ */
+ public function toFormattedDateString();
+
+ /**
+ * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept:
+ * 1977-04-22T01:00:00-05:00).
+ *
+ * @example
+ * ```
+ * echo Carbon::now('America/Toronto')->toISOString() . "\n";
+ * echo Carbon::now('America/Toronto')->toISOString(true) . "\n";
+ * ```
+ *
+ * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC.
+ *
+ * @return null|string
+ */
+ public function toISOString($keepOffset = false);
+
+ /**
+ * Return a immutable copy of the instance.
+ *
+ * @return CarbonImmutable
+ */
+ public function toImmutable();
+
+ /**
+ * Format the instance as ISO8601
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toIso8601String();
+ * ```
+ *
+ * @return string
+ */
+ public function toIso8601String();
+
+ /**
+ * Convert the instance to UTC and return as Zulu ISO8601
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toIso8601ZuluString();
+ * ```
+ *
+ * @param string $unitPrecision
+ *
+ * @return string
+ */
+ public function toIso8601ZuluString($unitPrecision = 'second');
+
+ /**
+ * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone.
+ *
+ * @example
+ * ```
+ * echo Carbon::now('America/Toronto')->toJSON();
+ * ```
+ *
+ * @return null|string
+ */
+ public function toJSON();
+
+ /**
+ * Return a mutable copy of the instance.
+ *
+ * @return Carbon
+ */
+ public function toMutable();
+
+ /**
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given to now
+ *
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single part)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function toNow($syntax = null, $short = false, $parts = 1, $options = null);
+
+ /**
+ * Get default object representation.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toObject());
+ * ```
+ *
+ * @return object
+ */
+ public function toObject();
+
+ /**
+ * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval).
+ *
+ * @param \DateTimeInterface|Carbon|CarbonImmutable|int|null $end period end date or recurrences count if int
+ * @param int|\DateInterval|string|null $interval period default interval or number of the given $unit
+ * @param string|null $unit if specified, $interval must be an integer
+ *
+ * @return CarbonPeriod
+ */
+ public function toPeriod($end = null, $interval = null, $unit = null);
+
+ /**
+ * Format the instance as RFC1036
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc1036String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc1036String();
+
+ /**
+ * Format the instance as RFC1123
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc1123String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc1123String();
+
+ /**
+ * Format the instance as RFC2822
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc2822String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc2822String();
+
+ /**
+ * Format the instance as RFC3339
+ *
+ * @param bool $extended
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc3339String() . "\n";
+ * echo Carbon::now()->toRfc3339String(true) . "\n";
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc3339String($extended = false);
+
+ /**
+ * Format the instance as RFC7231
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc7231String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc7231String();
+
+ /**
+ * Format the instance as RFC822
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc822String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc822String();
+
+ /**
+ * Format the instance as RFC850
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc850String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc850String();
+
+ /**
+ * Format the instance as RSS
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRssString();
+ * ```
+ *
+ * @return string
+ */
+ public function toRssString();
+
+ /**
+ * Returns english human readable complete date string.
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toString();
+ * ```
+ *
+ * @return string
+ */
+ public function toString();
+
+ /**
+ * Format the instance as time
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toTimeString();
+ * ```
+ *
+ * @param string $unitPrecision
+ *
+ * @return string
+ */
+ public function toTimeString($unitPrecision = 'second');
+
+ /**
+ * Format the instance as W3C
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toW3cString();
+ * ```
+ *
+ * @return string
+ */
+ public function toW3cString();
+
+ /**
+ * Create a Carbon instance for today.
+ *
+ * @param DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function today($tz = null);
+
+ /**
+ * Create a Carbon instance for tomorrow.
+ *
+ * @param DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function tomorrow($tz = null);
+
+ /**
+ * Translate using translation string or callback available.
+ *
+ * @param string $key
+ * @param array $parameters
+ * @param string|int|float|null $number
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator
+ *
+ * @return string
+ */
+ public function translate(string $key, array $parameters = [], $number = null, ?\Symfony\Component\Translation\TranslatorInterface $translator = null, bool $altNumbers = false): string;
+
+ /**
+ * Returns the alternative number for a given integer if available in the current locale.
+ *
+ * @param int $number
+ *
+ * @return string
+ */
+ public function translateNumber(int $number): string;
+
+ /**
+ * Translate a time string from a locale to an other.
+ *
+ * @param string $timeString date/time/duration string to translate (may also contain English)
+ * @param string|null $from input locale of the $timeString parameter (`Carbon::getLocale()` by default)
+ * @param string|null $to output locale of the result returned (`"en"` by default)
+ * @param int $mode specify what to translate with options:
+ * - self::TRANSLATE_ALL (default)
+ * - CarbonInterface::TRANSLATE_MONTHS
+ * - CarbonInterface::TRANSLATE_DAYS
+ * - CarbonInterface::TRANSLATE_UNITS
+ * - CarbonInterface::TRANSLATE_MERIDIEM
+ * You can use pipe to group: CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS
+ *
+ * @return string
+ */
+ public static function translateTimeString($timeString, $from = null, $to = null, $mode = self::TRANSLATE_ALL);
+
+ /**
+ * Translate a time string from the current locale (`$date->locale()`) to an other.
+ *
+ * @param string $timeString time string to translate
+ * @param string|null $to output locale of the result returned ("en" by default)
+ *
+ * @return string
+ */
+ public function translateTimeStringTo($timeString, $to = null);
+
+ /**
+ * Translate using translation string or callback available.
+ *
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator
+ * @param string $key
+ * @param array $parameters
+ * @param null $number
+ *
+ * @return string
+ */
+ public static function translateWith(\Symfony\Component\Translation\TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string;
+
+ /**
+ * Format as ->format() do (using date replacements patterns from https://php.net/manual/en/function.date.php)
+ * but translate words whenever possible (months, day names, etc.) using the current locale.
+ *
+ * @param string $format
+ *
+ * @return string
+ */
+ public function translatedFormat(string $format): string;
+
+ /**
+ * Set the timezone or returns the timezone name if no arguments passed.
+ *
+ * @param DateTimeZone|string $value
+ *
+ * @return static|string
+ */
+ public function tz($value = null);
+
+ /**
+ * @alias getTimestamp
+ *
+ * Returns the UNIX timestamp for the current date.
+ *
+ * @return int
+ */
+ public function unix();
+
+ /**
+ * @alias to
+ *
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given (or now if null given) to current instance.
+ *
+ * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
+ * if null passed, now will be used as comparison reference;
+ * if any other type, it will be converted to date and used as reference.
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * - 'other' entry (see above)
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single unit)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function until($other = null, $syntax = null, $short = false, $parts = 1, $options = null);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @see settings
+ *
+ * Indicates if months should be calculated with overflow.
+ *
+ * @param bool $monthsOverflow
+ *
+ * @return void
+ */
+ public static function useMonthsOverflow($monthsOverflow = true);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @see settings
+ *
+ * Enable the strict mode (or disable with passing false).
+ *
+ * @param bool $strictModeEnabled
+ */
+ public static function useStrictMode($strictModeEnabled = true);
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @see settings
+ *
+ * Indicates if years should be calculated with overflow.
+ *
+ * @param bool $yearsOverflow
+ *
+ * @return void
+ */
+ public static function useYearsOverflow($yearsOverflow = true);
+
+ /**
+ * Set the instance's timezone to UTC.
+ *
+ * @return static
+ */
+ public function utc();
+
+ /**
+ * Returns the minutes offset to UTC if no arguments passed, else set the timezone with given minutes shift passed.
+ *
+ * @param int|null $minuteOffset
+ *
+ * @return int|static
+ */
+ public function utcOffset(?int $minuteOffset = null);
+
+ /**
+ * Returns the milliseconds timestamps used amongst other by Date javascript objects.
+ *
+ * @return float
+ */
+ public function valueOf();
+
+ /**
+ * Get/set the week number using given first day of week and first
+ * day of year included in the first week. Or use US format if no settings
+ * given (Sunday / Jan 6).
+ *
+ * @param int|null $week
+ * @param int|null $dayOfWeek
+ * @param int|null $dayOfYear
+ *
+ * @return int|static
+ */
+ public function week($week = null, $dayOfWeek = null, $dayOfYear = null);
+
+ /**
+ * Set/get the week number of year using given first day of week and first
+ * day of year included in the first week. Or use US format if no settings
+ * given (Sunday / Jan 6).
+ *
+ * @param int|null $year if null, act as a getter, if not null, set the year and return current instance.
+ * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
+ * @param int|null $dayOfYear first day of year included in the week #1
+ *
+ * @return int|static
+ */
+ public function weekYear($year = null, $dayOfWeek = null, $dayOfYear = null);
+
+ /**
+ * Get/set the weekday from 0 (Sunday) to 6 (Saturday).
+ *
+ * @param int|null $value new value for weekday if using as setter.
+ *
+ * @return static|int
+ */
+ public function weekday($value = null);
+
+ /**
+ * Get the number of weeks of the current week-year using given first day of week and first
+ * day of year included in the first week. Or use US format if no settings
+ * given (Sunday / Jan 6).
+ *
+ * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
+ * @param int|null $dayOfYear first day of year included in the week #1
+ *
+ * @return int
+ */
+ public function weeksInYear($dayOfWeek = null, $dayOfYear = null);
+
+ /**
+ * Temporarily sets a static date to be used within the callback.
+ * Using setTestNow to set the date, executing the callback, then
+ * clearing the test instance.
+ *
+ * /!\ Use this method for unit tests only.
+ *
+ * @param Closure|static|string|false|null $testNow real or mock Carbon instance
+ * @param Closure|null $callback
+ *
+ * @return mixed
+ */
+ public static function withTestNow($testNow = null, $callback = null);
+
+ /**
+ * Create a Carbon instance for yesterday.
+ *
+ * @param DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function yesterday($tz = null);
+
+ // </methods>
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php
new file mode 100644
index 0000000..7168fa4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php
@@ -0,0 +1,2667 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use Carbon\Exceptions\BadFluentConstructorException;
+use Carbon\Exceptions\BadFluentSetterException;
+use Carbon\Exceptions\InvalidCastException;
+use Carbon\Exceptions\InvalidIntervalException;
+use Carbon\Exceptions\ParseErrorException;
+use Carbon\Exceptions\UnitNotConfiguredException;
+use Carbon\Exceptions\UnknownGetterException;
+use Carbon\Exceptions\UnknownSetterException;
+use Carbon\Exceptions\UnknownUnitException;
+use Carbon\Traits\IntervalRounding;
+use Carbon\Traits\IntervalStep;
+use Carbon\Traits\Mixin;
+use Carbon\Traits\Options;
+use Closure;
+use DateInterval;
+use Exception;
+use ReflectionException;
+use ReturnTypeWillChange;
+use Throwable;
+
+/**
+ * A simple API extension for DateInterval.
+ * The implementation provides helpers to handle weeks but only days are saved.
+ * Weeks are calculated based on the total days of the current instance.
+ *
+ * @property int $years Total years of the current interval.
+ * @property int $months Total months of the current interval.
+ * @property int $weeks Total weeks of the current interval calculated from the days.
+ * @property int $dayz Total days of the current interval (weeks * 7 + days).
+ * @property int $hours Total hours of the current interval.
+ * @property int $minutes Total minutes of the current interval.
+ * @property int $seconds Total seconds of the current interval.
+ * @property int $microseconds Total microseconds of the current interval.
+ * @property int $milliseconds Total microseconds of the current interval.
+ * @property int $microExcludeMilli Remaining microseconds without the milliseconds.
+ * @property int $dayzExcludeWeeks Total days remaining in the final week of the current instance (days % 7).
+ * @property int $daysExcludeWeeks alias of dayzExcludeWeeks
+ * @property-read float $totalYears Number of years equivalent to the interval.
+ * @property-read float $totalMonths Number of months equivalent to the interval.
+ * @property-read float $totalWeeks Number of weeks equivalent to the interval.
+ * @property-read float $totalDays Number of days equivalent to the interval.
+ * @property-read float $totalDayz Alias for totalDays.
+ * @property-read float $totalHours Number of hours equivalent to the interval.
+ * @property-read float $totalMinutes Number of minutes equivalent to the interval.
+ * @property-read float $totalSeconds Number of seconds equivalent to the interval.
+ * @property-read float $totalMilliseconds Number of milliseconds equivalent to the interval.
+ * @property-read float $totalMicroseconds Number of microseconds equivalent to the interval.
+ * @property-read string $locale locale of the current instance
+ *
+ * @method static CarbonInterval years($years = 1) Create instance specifying a number of years or modify the number of years if called on an instance.
+ * @method static CarbonInterval year($years = 1) Alias for years()
+ * @method static CarbonInterval months($months = 1) Create instance specifying a number of months or modify the number of months if called on an instance.
+ * @method static CarbonInterval month($months = 1) Alias for months()
+ * @method static CarbonInterval weeks($weeks = 1) Create instance specifying a number of weeks or modify the number of weeks if called on an instance.
+ * @method static CarbonInterval week($weeks = 1) Alias for weeks()
+ * @method static CarbonInterval days($days = 1) Create instance specifying a number of days or modify the number of days if called on an instance.
+ * @method static CarbonInterval dayz($days = 1) Alias for days()
+ * @method static CarbonInterval daysExcludeWeeks($days = 1) Create instance specifying a number of days or modify the number of days (keeping the current number of weeks) if called on an instance.
+ * @method static CarbonInterval dayzExcludeWeeks($days = 1) Alias for daysExcludeWeeks()
+ * @method static CarbonInterval day($days = 1) Alias for days()
+ * @method static CarbonInterval hours($hours = 1) Create instance specifying a number of hours or modify the number of hours if called on an instance.
+ * @method static CarbonInterval hour($hours = 1) Alias for hours()
+ * @method static CarbonInterval minutes($minutes = 1) Create instance specifying a number of minutes or modify the number of minutes if called on an instance.
+ * @method static CarbonInterval minute($minutes = 1) Alias for minutes()
+ * @method static CarbonInterval seconds($seconds = 1) Create instance specifying a number of seconds or modify the number of seconds if called on an instance.
+ * @method static CarbonInterval second($seconds = 1) Alias for seconds()
+ * @method static CarbonInterval milliseconds($milliseconds = 1) Create instance specifying a number of milliseconds or modify the number of milliseconds if called on an instance.
+ * @method static CarbonInterval millisecond($milliseconds = 1) Alias for milliseconds()
+ * @method static CarbonInterval microseconds($microseconds = 1) Create instance specifying a number of microseconds or modify the number of microseconds if called on an instance.
+ * @method static CarbonInterval microsecond($microseconds = 1) Alias for microseconds()
+ * @method $this addYears(int $years) Add given number of years to the current interval
+ * @method $this subYears(int $years) Subtract given number of years to the current interval
+ * @method $this addMonths(int $months) Add given number of months to the current interval
+ * @method $this subMonths(int $months) Subtract given number of months to the current interval
+ * @method $this addWeeks(int|float $weeks) Add given number of weeks to the current interval
+ * @method $this subWeeks(int|float $weeks) Subtract given number of weeks to the current interval
+ * @method $this addDays(int|float $days) Add given number of days to the current interval
+ * @method $this subDays(int|float $days) Subtract given number of days to the current interval
+ * @method $this addHours(int|float $hours) Add given number of hours to the current interval
+ * @method $this subHours(int|float $hours) Subtract given number of hours to the current interval
+ * @method $this addMinutes(int|float $minutes) Add given number of minutes to the current interval
+ * @method $this subMinutes(int|float $minutes) Subtract given number of minutes to the current interval
+ * @method $this addSeconds(int|float $seconds) Add given number of seconds to the current interval
+ * @method $this subSeconds(int|float $seconds) Subtract given number of seconds to the current interval
+ * @method $this addMilliseconds(int|float $milliseconds) Add given number of milliseconds to the current interval
+ * @method $this subMilliseconds(int|float $milliseconds) Subtract given number of milliseconds to the current interval
+ * @method $this addMicroseconds(int|float $microseconds) Add given number of microseconds to the current interval
+ * @method $this subMicroseconds(int|float $microseconds) Subtract given number of microseconds to the current interval
+ * @method $this roundYear(int|float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method $this roundYears(int|float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method $this floorYear(int|float $precision = 1) Truncate the current instance year with given precision.
+ * @method $this floorYears(int|float $precision = 1) Truncate the current instance year with given precision.
+ * @method $this ceilYear(int|float $precision = 1) Ceil the current instance year with given precision.
+ * @method $this ceilYears(int|float $precision = 1) Ceil the current instance year with given precision.
+ * @method $this roundMonth(int|float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method $this roundMonths(int|float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method $this floorMonth(int|float $precision = 1) Truncate the current instance month with given precision.
+ * @method $this floorMonths(int|float $precision = 1) Truncate the current instance month with given precision.
+ * @method $this ceilMonth(int|float $precision = 1) Ceil the current instance month with given precision.
+ * @method $this ceilMonths(int|float $precision = 1) Ceil the current instance month with given precision.
+ * @method $this roundWeek(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method $this roundWeeks(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method $this floorWeek(int|float $precision = 1) Truncate the current instance day with given precision.
+ * @method $this floorWeeks(int|float $precision = 1) Truncate the current instance day with given precision.
+ * @method $this ceilWeek(int|float $precision = 1) Ceil the current instance day with given precision.
+ * @method $this ceilWeeks(int|float $precision = 1) Ceil the current instance day with given precision.
+ * @method $this roundDay(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method $this roundDays(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method $this floorDay(int|float $precision = 1) Truncate the current instance day with given precision.
+ * @method $this floorDays(int|float $precision = 1) Truncate the current instance day with given precision.
+ * @method $this ceilDay(int|float $precision = 1) Ceil the current instance day with given precision.
+ * @method $this ceilDays(int|float $precision = 1) Ceil the current instance day with given precision.
+ * @method $this roundHour(int|float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method $this roundHours(int|float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method $this floorHour(int|float $precision = 1) Truncate the current instance hour with given precision.
+ * @method $this floorHours(int|float $precision = 1) Truncate the current instance hour with given precision.
+ * @method $this ceilHour(int|float $precision = 1) Ceil the current instance hour with given precision.
+ * @method $this ceilHours(int|float $precision = 1) Ceil the current instance hour with given precision.
+ * @method $this roundMinute(int|float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method $this roundMinutes(int|float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method $this floorMinute(int|float $precision = 1) Truncate the current instance minute with given precision.
+ * @method $this floorMinutes(int|float $precision = 1) Truncate the current instance minute with given precision.
+ * @method $this ceilMinute(int|float $precision = 1) Ceil the current instance minute with given precision.
+ * @method $this ceilMinutes(int|float $precision = 1) Ceil the current instance minute with given precision.
+ * @method $this roundSecond(int|float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method $this roundSeconds(int|float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method $this floorSecond(int|float $precision = 1) Truncate the current instance second with given precision.
+ * @method $this floorSeconds(int|float $precision = 1) Truncate the current instance second with given precision.
+ * @method $this ceilSecond(int|float $precision = 1) Ceil the current instance second with given precision.
+ * @method $this ceilSeconds(int|float $precision = 1) Ceil the current instance second with given precision.
+ * @method $this roundMillennium(int|float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method $this roundMillennia(int|float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method $this floorMillennium(int|float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method $this floorMillennia(int|float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method $this ceilMillennium(int|float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method $this ceilMillennia(int|float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method $this roundCentury(int|float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method $this roundCenturies(int|float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method $this floorCentury(int|float $precision = 1) Truncate the current instance century with given precision.
+ * @method $this floorCenturies(int|float $precision = 1) Truncate the current instance century with given precision.
+ * @method $this ceilCentury(int|float $precision = 1) Ceil the current instance century with given precision.
+ * @method $this ceilCenturies(int|float $precision = 1) Ceil the current instance century with given precision.
+ * @method $this roundDecade(int|float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method $this roundDecades(int|float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method $this floorDecade(int|float $precision = 1) Truncate the current instance decade with given precision.
+ * @method $this floorDecades(int|float $precision = 1) Truncate the current instance decade with given precision.
+ * @method $this ceilDecade(int|float $precision = 1) Ceil the current instance decade with given precision.
+ * @method $this ceilDecades(int|float $precision = 1) Ceil the current instance decade with given precision.
+ * @method $this roundQuarter(int|float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method $this roundQuarters(int|float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method $this floorQuarter(int|float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method $this floorQuarters(int|float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method $this ceilQuarter(int|float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method $this ceilQuarters(int|float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method $this roundMillisecond(int|float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method $this roundMilliseconds(int|float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method $this floorMillisecond(int|float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method $this floorMilliseconds(int|float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method $this ceilMillisecond(int|float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method $this ceilMilliseconds(int|float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method $this roundMicrosecond(int|float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method $this roundMicroseconds(int|float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method $this floorMicrosecond(int|float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method $this floorMicroseconds(int|float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method $this ceilMicrosecond(int|float $precision = 1) Ceil the current instance microsecond with given precision.
+ * @method $this ceilMicroseconds(int|float $precision = 1) Ceil the current instance microsecond with given precision.
+ */
+class CarbonInterval extends DateInterval implements CarbonConverterInterface
+{
+ use IntervalRounding;
+ use IntervalStep;
+ use Mixin {
+ Mixin::mixin as baseMixin;
+ }
+ use Options;
+
+ /**
+ * Interval spec period designators
+ */
+ const PERIOD_PREFIX = 'P';
+ const PERIOD_YEARS = 'Y';
+ const PERIOD_MONTHS = 'M';
+ const PERIOD_DAYS = 'D';
+ const PERIOD_TIME_PREFIX = 'T';
+ const PERIOD_HOURS = 'H';
+ const PERIOD_MINUTES = 'M';
+ const PERIOD_SECONDS = 'S';
+
+ /**
+ * A translator to ... er ... translate stuff
+ *
+ * @var \Symfony\Component\Translation\TranslatorInterface
+ */
+ protected static $translator;
+
+ /**
+ * @var array|null
+ */
+ protected static $cascadeFactors;
+
+ /**
+ * @var array
+ */
+ protected static $formats = [
+ 'y' => 'y',
+ 'Y' => 'y',
+ 'o' => 'y',
+ 'm' => 'm',
+ 'n' => 'm',
+ 'W' => 'weeks',
+ 'd' => 'd',
+ 'j' => 'd',
+ 'z' => 'd',
+ 'h' => 'h',
+ 'g' => 'h',
+ 'H' => 'h',
+ 'G' => 'h',
+ 'i' => 'i',
+ 's' => 's',
+ 'u' => 'micro',
+ 'v' => 'milli',
+ ];
+
+ /**
+ * @var array|null
+ */
+ private static $flipCascadeFactors;
+
+ /**
+ * The registered macros.
+ *
+ * @var array
+ */
+ protected static $macros = [];
+
+ /**
+ * Timezone handler for settings() method.
+ *
+ * @var mixed
+ */
+ protected $tzName;
+
+ /**
+ * Set the instance's timezone from a string or object and add/subtract the offset difference.
+ *
+ * @param \DateTimeZone|string $tzName
+ *
+ * @return static
+ */
+ public function shiftTimezone($tzName)
+ {
+ $this->tzName = $tzName;
+
+ return $this;
+ }
+
+ /**
+ * Mapping of units and factors for cascading.
+ *
+ * Should only be modified by changing the factors or referenced constants.
+ *
+ * @return array
+ */
+ public static function getCascadeFactors()
+ {
+ return static::$cascadeFactors ?: [
+ 'milliseconds' => [Carbon::MICROSECONDS_PER_MILLISECOND, 'microseconds'],
+ 'seconds' => [Carbon::MILLISECONDS_PER_SECOND, 'milliseconds'],
+ 'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'],
+ 'hours' => [Carbon::MINUTES_PER_HOUR, 'minutes'],
+ 'dayz' => [Carbon::HOURS_PER_DAY, 'hours'],
+ 'weeks' => [Carbon::DAYS_PER_WEEK, 'dayz'],
+ 'months' => [Carbon::WEEKS_PER_MONTH, 'weeks'],
+ 'years' => [Carbon::MONTHS_PER_YEAR, 'months'],
+ ];
+ }
+
+ private static function standardizeUnit($unit)
+ {
+ $unit = rtrim($unit, 'sz').'s';
+
+ return $unit === 'days' ? 'dayz' : $unit;
+ }
+
+ private static function getFlipCascadeFactors()
+ {
+ if (!self::$flipCascadeFactors) {
+ self::$flipCascadeFactors = [];
+
+ foreach (static::getCascadeFactors() as $to => [$factor, $from]) {
+ self::$flipCascadeFactors[self::standardizeUnit($from)] = [self::standardizeUnit($to), $factor];
+ }
+ }
+
+ return self::$flipCascadeFactors;
+ }
+
+ /**
+ * Set default cascading factors for ->cascade() method.
+ *
+ * @param array $cascadeFactors
+ */
+ public static function setCascadeFactors(array $cascadeFactors)
+ {
+ self::$flipCascadeFactors = null;
+ static::$cascadeFactors = $cascadeFactors;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //////////////////////////// CONSTRUCTORS /////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Create a new CarbonInterval instance.
+ *
+ * @param int|null $years
+ * @param int|null $months
+ * @param int|null $weeks
+ * @param int|null $days
+ * @param int|null $hours
+ * @param int|null $minutes
+ * @param int|null $seconds
+ * @param int|null $microseconds
+ *
+ * @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval.
+ */
+ public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
+ {
+ if ($years instanceof Closure) {
+ $this->step = $years;
+ $years = null;
+ }
+
+ if ($years instanceof DateInterval) {
+ parent::__construct(static::getDateIntervalSpec($years));
+ $this->f = $years->f;
+ static::copyNegativeUnits($years, $this);
+
+ return;
+ }
+
+ $spec = $years;
+
+ if (!\is_string($spec) || (float) $years || preg_match('/^[0-9.]/', $years)) {
+ $spec = static::PERIOD_PREFIX;
+
+ $spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
+ $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';
+
+ $specDays = 0;
+ $specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0;
+ $specDays += $days > 0 ? $days : 0;
+
+ $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';
+
+ if ($hours > 0 || $minutes > 0 || $seconds > 0) {
+ $spec .= static::PERIOD_TIME_PREFIX;
+ $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
+ $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
+ $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
+ }
+
+ if ($spec === static::PERIOD_PREFIX) {
+ // Allow the zero interval.
+ $spec .= '0'.static::PERIOD_YEARS;
+ }
+ }
+
+ parent::__construct($spec);
+
+ if ($microseconds !== null) {
+ $this->f = $microseconds / Carbon::MICROSECONDS_PER_SECOND;
+ }
+ }
+
+ /**
+ * Returns the factor for a given source-to-target couple.
+ *
+ * @param string $source
+ * @param string $target
+ *
+ * @return int|null
+ */
+ public static function getFactor($source, $target)
+ {
+ $source = self::standardizeUnit($source);
+ $target = self::standardizeUnit($target);
+ $factors = static::getFlipCascadeFactors();
+
+ if (isset($factors[$source])) {
+ [$to, $factor] = $factors[$source];
+
+ if ($to === $target) {
+ return $factor;
+ }
+
+ return $factor * static::getFactor($to, $target);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns current config for days per week.
+ *
+ * @return int
+ */
+ public static function getDaysPerWeek()
+ {
+ return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK;
+ }
+
+ /**
+ * Returns current config for hours per day.
+ *
+ * @return int
+ */
+ public static function getHoursPerDay()
+ {
+ return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY;
+ }
+
+ /**
+ * Returns current config for minutes per hour.
+ *
+ * @return int
+ */
+ public static function getMinutesPerHour()
+ {
+ return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR;
+ }
+
+ /**
+ * Returns current config for seconds per minute.
+ *
+ * @return int
+ */
+ public static function getSecondsPerMinute()
+ {
+ return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE;
+ }
+
+ /**
+ * Returns current config for microseconds per second.
+ *
+ * @return int
+ */
+ public static function getMillisecondsPerSecond()
+ {
+ return static::getFactor('milliseconds', 'seconds') ?: Carbon::MILLISECONDS_PER_SECOND;
+ }
+
+ /**
+ * Returns current config for microseconds per second.
+ *
+ * @return int
+ */
+ public static function getMicrosecondsPerMillisecond()
+ {
+ return static::getFactor('microseconds', 'milliseconds') ?: Carbon::MICROSECONDS_PER_MILLISECOND;
+ }
+
+ /**
+ * Create a new CarbonInterval instance from specific values.
+ * This is an alias for the constructor that allows better fluent
+ * syntax as it allows you to do CarbonInterval::create(1)->fn() rather than
+ * (new CarbonInterval(1))->fn().
+ *
+ * @param int $years
+ * @param int $months
+ * @param int $weeks
+ * @param int $days
+ * @param int $hours
+ * @param int $minutes
+ * @param int $seconds
+ * @param int $microseconds
+ *
+ * @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval.
+ *
+ * @return static
+ */
+ public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
+ {
+ return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
+ }
+
+ /**
+ * Parse a string into a new CarbonInterval object according to the specified format.
+ *
+ * @example
+ * ```
+ * echo Carboninterval::createFromFormat('H:i', '1:30');
+ * ```
+ *
+ * @param string $format Format of the $interval input string
+ * @param string $interval Input string to convert into an interval
+ *
+ * @throws Exception when the $interval cannot be parsed as an interval.
+ *
+ * @return static
+ */
+ public static function createFromFormat(string $format, ?string $interval)
+ {
+ $instance = new static(0);
+ $length = mb_strlen($format);
+
+ if (preg_match('/s([,.])([uv])$/', $format, $match)) {
+ $interval = explode($match[1], $interval);
+ $index = \count($interval) - 1;
+ $interval[$index] = str_pad($interval[$index], $match[2] === 'v' ? 3 : 6, '0');
+ $interval = implode($match[1], $interval);
+ }
+
+ $interval = $interval ?? '';
+
+ for ($index = 0; $index < $length; $index++) {
+ $expected = mb_substr($format, $index, 1);
+ $nextCharacter = mb_substr($interval, 0, 1);
+ $unit = static::$formats[$expected] ?? null;
+
+ if ($unit) {
+ if (!preg_match('/^-?\d+/', $interval, $match)) {
+ throw new ParseErrorException('number', $nextCharacter);
+ }
+
+ $interval = mb_substr($interval, mb_strlen($match[0]));
+ $instance->$unit += (int) ($match[0]);
+
+ continue;
+ }
+
+ if ($nextCharacter !== $expected) {
+ throw new ParseErrorException(
+ "'$expected'",
+ $nextCharacter,
+ 'Allowed substitutes for interval formats are '.implode(', ', array_keys(static::$formats))."\n".
+ 'See https://php.net/manual/en/function.date.php for their meaning'
+ );
+ }
+
+ $interval = mb_substr($interval, 1);
+ }
+
+ if ($interval !== '') {
+ throw new ParseErrorException(
+ 'end of string',
+ $interval
+ );
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Get a copy of the instance.
+ *
+ * @return static
+ */
+ public function copy()
+ {
+ $date = new static(0);
+ $date->copyProperties($this);
+ $date->step = $this->step;
+
+ return $date;
+ }
+
+ /**
+ * Get a copy of the instance.
+ *
+ * @return static
+ */
+ public function clone()
+ {
+ return $this->copy();
+ }
+
+ /**
+ * Provide static helpers to create instances. Allows CarbonInterval::years(3).
+ *
+ * Note: This is done using the magic method to allow static and instance methods to
+ * have the same names.
+ *
+ * @param string $method magic method name called
+ * @param array $parameters parameters list
+ *
+ * @return static|null
+ */
+ public static function __callStatic($method, $parameters)
+ {
+ try {
+ $interval = new static(0);
+ $localStrictModeEnabled = $interval->localStrictModeEnabled;
+ $interval->localStrictModeEnabled = true;
+
+ $result = static::hasMacro($method)
+ ? static::bindMacroContext(null, function () use (&$method, &$parameters, &$interval) {
+ return $interval->callMacro($method, $parameters);
+ })
+ : $interval->$method(...$parameters);
+
+ $interval->localStrictModeEnabled = $localStrictModeEnabled;
+
+ return $result;
+ } catch (BadFluentSetterException $exception) {
+ if (Carbon::isStrictModeEnabled()) {
+ throw new BadFluentConstructorException($method, 0, $exception);
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Return the current context from inside a macro callee or a new one if static.
+ *
+ * @return static
+ */
+ protected static function this()
+ {
+ return end(static::$macroContextStack) ?: new static(0);
+ }
+
+ /**
+ * Creates a CarbonInterval from string.
+ *
+ * Format:
+ *
+ * Suffix | Unit | Example | DateInterval expression
+ * -------|---------|---------|------------------------
+ * y | years | 1y | P1Y
+ * mo | months | 3mo | P3M
+ * w | weeks | 2w | P2W
+ * d | days | 28d | P28D
+ * h | hours | 4h | PT4H
+ * m | minutes | 12m | PT12M
+ * s | seconds | 59s | PT59S
+ *
+ * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds.
+ *
+ * Special cases:
+ * - An empty string will return a zero interval
+ * - Fractions are allowed for weeks, days, hours and minutes and will be converted
+ * and rounded to the next smaller value (caution: 0.5w = 4d)
+ *
+ * @param string $intervalDefinition
+ *
+ * @return static
+ */
+ public static function fromString($intervalDefinition)
+ {
+ if (empty($intervalDefinition)) {
+ return new static(0);
+ }
+
+ $years = 0;
+ $months = 0;
+ $weeks = 0;
+ $days = 0;
+ $hours = 0;
+ $minutes = 0;
+ $seconds = 0;
+ $milliseconds = 0;
+ $microseconds = 0;
+
+ $pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i';
+ preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
+
+ while ([$part, $value, $unit] = array_shift($parts)) {
+ $intValue = (int) $value;
+ $fraction = (float) $value - $intValue;
+
+ // Fix calculation precision
+ switch (round($fraction, 6)) {
+ case 1:
+ $fraction = 0;
+ $intValue++;
+
+ break;
+ case 0:
+ $fraction = 0;
+
+ break;
+ }
+
+ switch ($unit === 'µs' ? 'µs' : strtolower($unit)) {
+ case 'millennia':
+ case 'millennium':
+ $years += $intValue * CarbonInterface::YEARS_PER_MILLENNIUM;
+
+ break;
+
+ case 'century':
+ case 'centuries':
+ $years += $intValue * CarbonInterface::YEARS_PER_CENTURY;
+
+ break;
+
+ case 'decade':
+ case 'decades':
+ $years += $intValue * CarbonInterface::YEARS_PER_DECADE;
+
+ break;
+
+ case 'year':
+ case 'years':
+ case 'y':
+ $years += $intValue;
+
+ break;
+
+ case 'quarter':
+ case 'quarters':
+ $months += $intValue * CarbonInterface::MONTHS_PER_QUARTER;
+
+ break;
+
+ case 'month':
+ case 'months':
+ case 'mo':
+ $months += $intValue;
+
+ break;
+
+ case 'week':
+ case 'weeks':
+ case 'w':
+ $weeks += $intValue;
+
+ if ($fraction) {
+ $parts[] = [null, $fraction * static::getDaysPerWeek(), 'd'];
+ }
+
+ break;
+
+ case 'day':
+ case 'days':
+ case 'd':
+ $days += $intValue;
+
+ if ($fraction) {
+ $parts[] = [null, $fraction * static::getHoursPerDay(), 'h'];
+ }
+
+ break;
+
+ case 'hour':
+ case 'hours':
+ case 'h':
+ $hours += $intValue;
+
+ if ($fraction) {
+ $parts[] = [null, $fraction * static::getMinutesPerHour(), 'm'];
+ }
+
+ break;
+
+ case 'minute':
+ case 'minutes':
+ case 'm':
+ $minutes += $intValue;
+
+ if ($fraction) {
+ $parts[] = [null, $fraction * static::getSecondsPerMinute(), 's'];
+ }
+
+ break;
+
+ case 'second':
+ case 'seconds':
+ case 's':
+ $seconds += $intValue;
+
+ if ($fraction) {
+ $parts[] = [null, $fraction * static::getMillisecondsPerSecond(), 'ms'];
+ }
+
+ break;
+
+ case 'millisecond':
+ case 'milliseconds':
+ case 'milli':
+ case 'ms':
+ $milliseconds += $intValue;
+
+ if ($fraction) {
+ $microseconds += round($fraction * static::getMicrosecondsPerMillisecond());
+ }
+
+ break;
+
+ case 'microsecond':
+ case 'microseconds':
+ case 'micro':
+ case 'µs':
+ $microseconds += $intValue;
+
+ break;
+
+ default:
+ throw new InvalidIntervalException(
+ sprintf('Invalid part %s in definition %s', $part, $intervalDefinition)
+ );
+ }
+ }
+
+ return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $milliseconds * Carbon::MICROSECONDS_PER_MILLISECOND + $microseconds);
+ }
+
+ /**
+ * Creates a CarbonInterval from string using a different locale.
+ *
+ * @param string $interval interval string in the given language (may also contain English).
+ * @param string|null $locale if locale is null or not specified, current global locale will be used instead.
+ *
+ * @return static
+ */
+ public static function parseFromLocale($interval, $locale = null)
+ {
+ return static::fromString(Carbon::translateTimeString($interval, $locale ?: static::getLocale(), 'en'));
+ }
+
+ private static function castIntervalToClass(DateInterval $interval, string $className)
+ {
+ $mainClass = DateInterval::class;
+
+ if (!is_a($className, $mainClass, true)) {
+ throw new InvalidCastException("$className is not a sub-class of $mainClass.");
+ }
+
+ $microseconds = $interval->f;
+ $instance = new $className(static::getDateIntervalSpec($interval));
+
+ if ($microseconds) {
+ $instance->f = $microseconds;
+ }
+
+ if ($interval instanceof self && is_a($className, self::class, true)) {
+ static::copyStep($interval, $instance);
+ }
+
+ static::copyNegativeUnits($interval, $instance);
+
+ return $instance;
+ }
+
+ private static function copyNegativeUnits(DateInterval $from, DateInterval $to): void
+ {
+ $to->invert = $from->invert;
+
+ foreach (['y', 'm', 'd', 'h', 'i', 's'] as $unit) {
+ if ($from->$unit < 0) {
+ $to->$unit *= -1;
+ }
+ }
+ }
+
+ private static function copyStep(self $from, self $to): void
+ {
+ $to->setStep($from->getStep());
+ }
+
+ /**
+ * Cast the current instance into the given class.
+ *
+ * @param string $className The $className::instance() method will be called to cast the current object.
+ *
+ * @return DateInterval
+ */
+ public function cast(string $className)
+ {
+ return self::castIntervalToClass($this, $className);
+ }
+
+ /**
+ * Create a CarbonInterval instance from a DateInterval one. Can not instance
+ * DateInterval objects created from DateTime::diff() as you can't externally
+ * set the $days field.
+ *
+ * @param DateInterval $interval
+ *
+ * @return static
+ */
+ public static function instance(DateInterval $interval)
+ {
+ return self::castIntervalToClass($interval, static::class);
+ }
+
+ /**
+ * Make a CarbonInterval instance from given variable if possible.
+ *
+ * Always return a new instance. Parse only strings and only these likely to be intervals (skip dates
+ * and recurrences). Throw an exception for invalid format, but otherwise return null.
+ *
+ * @param mixed|int|DateInterval|string|Closure|null $interval interval or number of the given $unit
+ * @param string|null $unit if specified, $interval must be an integer
+ *
+ * @return static|null
+ */
+ public static function make($interval, $unit = null)
+ {
+ if ($unit) {
+ $interval = "$interval ".Carbon::pluralUnit($unit);
+ }
+
+ if ($interval instanceof DateInterval) {
+ return static::instance($interval);
+ }
+
+ if ($interval instanceof Closure) {
+ return new static($interval);
+ }
+
+ if (!\is_string($interval)) {
+ return null;
+ }
+
+ return static::makeFromString($interval);
+ }
+
+ protected static function makeFromString(string $interval)
+ {
+ $interval = preg_replace('/\s+/', ' ', trim($interval));
+
+ if (preg_match('/^P[T0-9]/', $interval)) {
+ return new static($interval);
+ }
+
+ if (preg_match('/^(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+$/i', $interval)) {
+ return static::fromString($interval);
+ }
+
+ /** @var static $interval */
+ $interval = static::createFromDateString($interval);
+
+ return !$interval || $interval->isEmpty() ? null : $interval;
+ }
+
+ protected function resolveInterval($interval)
+ {
+ if (!($interval instanceof self)) {
+ return self::make($interval);
+ }
+
+ return $interval;
+ }
+
+ /**
+ * Sets up a DateInterval from the relative parts of the string.
+ *
+ * @param string $time
+ *
+ * @return static
+ *
+ * @link https://php.net/manual/en/dateinterval.createfromdatestring.php
+ */
+ #[ReturnTypeWillChange]
+ public static function createFromDateString($time)
+ {
+ $interval = @parent::createFromDateString(strtr($time, [
+ ',' => ' ',
+ ' and ' => ' ',
+ ]));
+
+ if ($interval instanceof DateInterval) {
+ $interval = static::instance($interval);
+ }
+
+ return $interval;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ ///////////////////////// GETTERS AND SETTERS /////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Get a part of the CarbonInterval object.
+ *
+ * @param string $name
+ *
+ * @throws UnknownGetterException
+ *
+ * @return int|float|string
+ */
+ public function get($name)
+ {
+ if (str_starts_with($name, 'total')) {
+ return $this->total(substr($name, 5));
+ }
+
+ switch ($name) {
+ case 'years':
+ return $this->y;
+
+ case 'months':
+ return $this->m;
+
+ case 'dayz':
+ return $this->d;
+
+ case 'hours':
+ return $this->h;
+
+ case 'minutes':
+ return $this->i;
+
+ case 'seconds':
+ return $this->s;
+
+ case 'milli':
+ case 'milliseconds':
+ return (int) (round($this->f * Carbon::MICROSECONDS_PER_SECOND) / Carbon::MICROSECONDS_PER_MILLISECOND);
+
+ case 'micro':
+ case 'microseconds':
+ return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND);
+
+ case 'microExcludeMilli':
+ return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND) % Carbon::MICROSECONDS_PER_MILLISECOND;
+
+ case 'weeks':
+ return (int) ($this->d / static::getDaysPerWeek());
+
+ case 'daysExcludeWeeks':
+ case 'dayzExcludeWeeks':
+ return $this->d % static::getDaysPerWeek();
+
+ case 'locale':
+ return $this->getTranslatorLocale();
+
+ default:
+ throw new UnknownGetterException($name);
+ }
+ }
+
+ /**
+ * Get a part of the CarbonInterval object.
+ *
+ * @param string $name
+ *
+ * @throws UnknownGetterException
+ *
+ * @return int|float|string
+ */
+ public function __get($name)
+ {
+ return $this->get($name);
+ }
+
+ /**
+ * Set a part of the CarbonInterval object.
+ *
+ * @param string|array $name
+ * @param int $value
+ *
+ * @throws UnknownSetterException
+ *
+ * @return $this
+ */
+ public function set($name, $value = null)
+ {
+ $properties = \is_array($name) ? $name : [$name => $value];
+
+ foreach ($properties as $key => $value) {
+ switch (Carbon::singularUnit(rtrim($key, 'z'))) {
+ case 'year':
+ $this->y = $value;
+
+ break;
+
+ case 'month':
+ $this->m = $value;
+
+ break;
+
+ case 'week':
+ $this->d = $value * static::getDaysPerWeek();
+
+ break;
+
+ case 'day':
+ $this->d = $value;
+
+ break;
+
+ case 'daysexcludeweek':
+ case 'dayzexcludeweek':
+ $this->d = $this->weeks * static::getDaysPerWeek() + $value;
+
+ break;
+
+ case 'hour':
+ $this->h = $value;
+
+ break;
+
+ case 'minute':
+ $this->i = $value;
+
+ break;
+
+ case 'second':
+ $this->s = $value;
+
+ break;
+
+ case 'milli':
+ case 'millisecond':
+ $this->microseconds = $value * Carbon::MICROSECONDS_PER_MILLISECOND + $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND;
+
+ break;
+
+ case 'micro':
+ case 'microsecond':
+ $this->f = $value / Carbon::MICROSECONDS_PER_SECOND;
+
+ break;
+
+ default:
+ if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
+ throw new UnknownSetterException($key);
+ }
+
+ $this->$key = $value;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set a part of the CarbonInterval object.
+ *
+ * @param string $name
+ * @param int $value
+ *
+ * @throws UnknownSetterException
+ */
+ public function __set($name, $value)
+ {
+ $this->set($name, $value);
+ }
+
+ /**
+ * Allow setting of weeks and days to be cumulative.
+ *
+ * @param int $weeks Number of weeks to set
+ * @param int $days Number of days to set
+ *
+ * @return static
+ */
+ public function weeksAndDays($weeks, $days)
+ {
+ $this->dayz = ($weeks * static::getDaysPerWeek()) + $days;
+
+ return $this;
+ }
+
+ /**
+ * Returns true if the interval is empty for each unit.
+ *
+ * @return bool
+ */
+ public function isEmpty()
+ {
+ return $this->years === 0 &&
+ $this->months === 0 &&
+ $this->dayz === 0 &&
+ !$this->days &&
+ $this->hours === 0 &&
+ $this->minutes === 0 &&
+ $this->seconds === 0 &&
+ $this->microseconds === 0;
+ }
+
+ /**
+ * Register a custom macro.
+ *
+ * @example
+ * ```
+ * CarbonInterval::macro('twice', function () {
+ * return $this->times(2);
+ * });
+ * echo CarbonInterval::hours(2)->twice();
+ * ```
+ *
+ * @param string $name
+ * @param object|callable $macro
+ *
+ * @return void
+ */
+ public static function macro($name, $macro)
+ {
+ static::$macros[$name] = $macro;
+ }
+
+ /**
+ * Register macros from a mixin object.
+ *
+ * @example
+ * ```
+ * CarbonInterval::mixin(new class {
+ * public function daysToHours() {
+ * return function () {
+ * $this->hours += $this->days;
+ * $this->days = 0;
+ *
+ * return $this;
+ * };
+ * }
+ * public function hoursToDays() {
+ * return function () {
+ * $this->days += $this->hours;
+ * $this->hours = 0;
+ *
+ * return $this;
+ * };
+ * }
+ * });
+ * echo CarbonInterval::hours(5)->hoursToDays() . "\n";
+ * echo CarbonInterval::days(5)->daysToHours() . "\n";
+ * ```
+ *
+ * @param object|string $mixin
+ *
+ * @throws ReflectionException
+ *
+ * @return void
+ */
+ public static function mixin($mixin)
+ {
+ static::baseMixin($mixin);
+ }
+
+ /**
+ * Check if macro is registered.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public static function hasMacro($name)
+ {
+ return isset(static::$macros[$name]);
+ }
+
+ /**
+ * Call given macro.
+ *
+ * @param string $name
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ protected function callMacro($name, $parameters)
+ {
+ $macro = static::$macros[$name];
+
+ if ($macro instanceof Closure) {
+ $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class);
+
+ return ($boundMacro ?: $macro)(...$parameters);
+ }
+
+ return $macro(...$parameters);
+ }
+
+ /**
+ * Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day().
+ *
+ * Note: This is done using the magic method to allow static and instance methods to
+ * have the same names.
+ *
+ * @param string $method magic method name called
+ * @param array $parameters parameters list
+ *
+ * @throws BadFluentSetterException|Throwable
+ *
+ * @return static
+ */
+ public function __call($method, $parameters)
+ {
+ if (static::hasMacro($method)) {
+ return static::bindMacroContext($this, function () use (&$method, &$parameters) {
+ return $this->callMacro($method, $parameters);
+ });
+ }
+
+ $roundedValue = $this->callRoundMethod($method, $parameters);
+
+ if ($roundedValue !== null) {
+ return $roundedValue;
+ }
+
+ if (preg_match('/^(?<method>add|sub)(?<unit>[A-Z].*)$/', $method, $match)) {
+ return $this->{$match['method']}($parameters[0], $match['unit']);
+ }
+
+ try {
+ $this->set($method, \count($parameters) === 0 ? 1 : $parameters[0]);
+ } catch (UnknownSetterException $exception) {
+ if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
+ throw new BadFluentSetterException($method, 0, $exception);
+ }
+ }
+
+ return $this;
+ }
+
+ protected function getForHumansInitialVariables($syntax, $short)
+ {
+ if (\is_array($syntax)) {
+ return $syntax;
+ }
+
+ if (\is_int($short)) {
+ return [
+ 'parts' => $short,
+ 'short' => false,
+ ];
+ }
+
+ if (\is_bool($syntax)) {
+ return [
+ 'short' => $syntax,
+ 'syntax' => CarbonInterface::DIFF_ABSOLUTE,
+ ];
+ }
+
+ return [];
+ }
+
+ /**
+ * @param mixed $syntax
+ * @param mixed $short
+ * @param mixed $parts
+ * @param mixed $options
+ *
+ * @return array
+ */
+ protected function getForHumansParameters($syntax = null, $short = false, $parts = -1, $options = null)
+ {
+ $optionalSpace = ' ';
+ $default = $this->getTranslationMessage('list.0') ?? $this->getTranslationMessage('list') ?? ' ';
+ $join = $default === '' ? '' : ' ';
+ $altNumbers = false;
+ $aUnit = false;
+ $minimumUnit = 's';
+ extract($this->getForHumansInitialVariables($syntax, $short));
+
+ if ($syntax === null) {
+ $syntax = CarbonInterface::DIFF_ABSOLUTE;
+ }
+
+ if ($parts === -1) {
+ $parts = INF;
+ }
+
+ if ($options === null) {
+ $options = static::getHumanDiffOptions();
+ }
+
+ if ($join === false) {
+ $join = ' ';
+ } elseif ($join === true) {
+ $join = [
+ $default,
+ $this->getTranslationMessage('list.1') ?? $default,
+ ];
+ }
+
+ if ($altNumbers) {
+ if ($altNumbers !== true) {
+ $language = new Language($this->locale);
+ $altNumbers = \in_array($language->getCode(), (array) $altNumbers);
+ }
+ }
+
+ if (\is_array($join)) {
+ [$default, $last] = $join;
+
+ if ($default !== ' ') {
+ $optionalSpace = '';
+ }
+
+ $join = function ($list) use ($default, $last) {
+ if (\count($list) < 2) {
+ return implode('', $list);
+ }
+
+ $end = array_pop($list);
+
+ return implode($default, $list).$last.$end;
+ };
+ }
+
+ if (\is_string($join)) {
+ if ($join !== ' ') {
+ $optionalSpace = '';
+ }
+
+ $glue = $join;
+ $join = function ($list) use ($glue) {
+ return implode($glue, $list);
+ };
+ }
+
+ $interpolations = [
+ ':optional-space' => $optionalSpace,
+ ];
+
+ return [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit];
+ }
+
+ protected static function getRoundingMethodFromOptions(int $options): ?string
+ {
+ if ($options & CarbonInterface::ROUND) {
+ return 'round';
+ }
+
+ if ($options & CarbonInterface::CEIL) {
+ return 'ceil';
+ }
+
+ if ($options & CarbonInterface::FLOOR) {
+ return 'floor';
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns interval values as an array where key are the unit names and values the counts.
+ *
+ * @return int[]
+ */
+ public function toArray()
+ {
+ return [
+ 'years' => $this->years,
+ 'months' => $this->months,
+ 'weeks' => $this->weeks,
+ 'days' => $this->daysExcludeWeeks,
+ 'hours' => $this->hours,
+ 'minutes' => $this->minutes,
+ 'seconds' => $this->seconds,
+ 'microseconds' => $this->microseconds,
+ ];
+ }
+
+ /**
+ * Returns interval non-zero values as an array where key are the unit names and values the counts.
+ *
+ * @return int[]
+ */
+ public function getNonZeroValues()
+ {
+ return array_filter($this->toArray(), 'intval');
+ }
+
+ /**
+ * Returns interval values as an array where key are the unit names and values the counts
+ * from the biggest non-zero one the the smallest non-zero one.
+ *
+ * @return int[]
+ */
+ public function getValuesSequence()
+ {
+ $nonZeroValues = $this->getNonZeroValues();
+
+ if ($nonZeroValues === []) {
+ return [];
+ }
+
+ $keys = array_keys($nonZeroValues);
+ $firstKey = $keys[0];
+ $lastKey = $keys[\count($keys) - 1];
+ $values = [];
+ $record = false;
+
+ foreach ($this->toArray() as $unit => $count) {
+ if ($unit === $firstKey) {
+ $record = true;
+ }
+
+ if ($record) {
+ $values[$unit] = $count;
+ }
+
+ if ($unit === $lastKey) {
+ $record = false;
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * Get the current interval in a human readable format in the current locale.
+ *
+ * @example
+ * ```
+ * echo CarbonInterval::fromString('4d 3h 40m')->forHumans() . "\n";
+ * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 2]) . "\n";
+ * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 3, 'join' => true]) . "\n";
+ * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['short' => true]) . "\n";
+ * echo CarbonInterval::fromString('1d 24h')->forHumans(['join' => ' or ']) . "\n";
+ * echo CarbonInterval::fromString('1d 24h')->forHumans(['minimumUnit' => 'hour']) . "\n";
+ * ```
+ *
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'aUnit' entry, prefer "an hour" over "1 hour" if true
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * - 'minimumUnit' entry determines the smallest unit of time to display can be long or
+ * ` short form of the units, e.g. 'hour' or 'h' (default value: s)
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: -1: no limits)
+ * @param int $options human diff options
+ *
+ * @throws Exception
+ *
+ * @return string
+ */
+ public function forHumans($syntax = null, $short = false, $parts = -1, $options = null)
+ {
+ [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit] = $this->getForHumansParameters($syntax, $short, $parts, $options);
+
+ $interval = [];
+
+ $syntax = (int) ($syntax === null ? CarbonInterface::DIFF_ABSOLUTE : $syntax);
+ $absolute = $syntax === CarbonInterface::DIFF_ABSOLUTE;
+ $relativeToNow = $syntax === CarbonInterface::DIFF_RELATIVE_TO_NOW;
+ $count = 1;
+ $unit = $short ? 's' : 'second';
+ $isFuture = $this->invert === 1;
+ $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
+
+ /** @var \Symfony\Component\Translation\Translator $translator */
+ $translator = $this->getLocalTranslator();
+
+ $handleDeclensions = function ($unit, $count) use ($interpolations, $transId, $translator, $altNumbers, $absolute) {
+ if (!$absolute) {
+ // Some languages have special pluralization for past and future tense.
+ $key = $unit.'_'.$transId;
+ $result = $this->translate($key, $interpolations, $count, $translator, $altNumbers);
+
+ if ($result !== $key) {
+ return $result;
+ }
+ }
+
+ $result = $this->translate($unit, $interpolations, $count, $translator, $altNumbers);
+
+ if ($result !== $unit) {
+ return $result;
+ }
+
+ return null;
+ };
+
+ $intervalValues = $this;
+ $method = static::getRoundingMethodFromOptions($options);
+
+ if ($method) {
+ $previousCount = INF;
+
+ while (
+ \count($intervalValues->getNonZeroValues()) > $parts &&
+ ($count = \count($keys = array_keys($intervalValues->getValuesSequence()))) > 1
+ ) {
+ $intervalValues = $this->copy()->roundUnit(
+ $keys[min($count, $previousCount - 1) - 2],
+ 1,
+ $method
+ );
+ $previousCount = $count;
+ }
+ }
+
+ $diffIntervalArray = [
+ ['value' => $intervalValues->years, 'unit' => 'year', 'unitShort' => 'y'],
+ ['value' => $intervalValues->months, 'unit' => 'month', 'unitShort' => 'm'],
+ ['value' => $intervalValues->weeks, 'unit' => 'week', 'unitShort' => 'w'],
+ ['value' => $intervalValues->daysExcludeWeeks, 'unit' => 'day', 'unitShort' => 'd'],
+ ['value' => $intervalValues->hours, 'unit' => 'hour', 'unitShort' => 'h'],
+ ['value' => $intervalValues->minutes, 'unit' => 'minute', 'unitShort' => 'min'],
+ ['value' => $intervalValues->seconds, 'unit' => 'second', 'unitShort' => 's'],
+ ['value' => $intervalValues->milliseconds, 'unit' => 'millisecond', 'unitShort' => 'ms'],
+ ['value' => $intervalValues->microExcludeMilli, 'unit' => 'microsecond', 'unitShort' => 'µs'],
+ ];
+
+ $transChoice = function ($short, $unitData) use ($absolute, $handleDeclensions, $translator, $aUnit, $altNumbers, $interpolations) {
+ $count = $unitData['value'];
+
+ if ($short) {
+ $result = $handleDeclensions($unitData['unitShort'], $count);
+
+ if ($result !== null) {
+ return $result;
+ }
+ } elseif ($aUnit) {
+ $result = $handleDeclensions('a_'.$unitData['unit'], $count);
+
+ if ($result !== null) {
+ return $result;
+ }
+ }
+
+ if (!$absolute) {
+ return $handleDeclensions($unitData['unit'], $count);
+ }
+
+ return $this->translate($unitData['unit'], $interpolations, $count, $translator, $altNumbers);
+ };
+
+ $fallbackUnit = ['second', 's'];
+ foreach ($diffIntervalArray as $diffIntervalData) {
+ if ($diffIntervalData['value'] > 0) {
+ $unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit'];
+ $count = $diffIntervalData['value'];
+ $interval[] = $transChoice($short, $diffIntervalData);
+ } elseif ($options & CarbonInterface::SEQUENTIAL_PARTS_ONLY && \count($interval) > 0) {
+ break;
+ }
+
+ // break the loop after we get the required number of parts in array
+ if (\count($interval) >= $parts) {
+ break;
+ }
+
+ // break the loop after we have reached the minimum unit
+ if (\in_array($minimumUnit, [$diffIntervalData['unit'], $diffIntervalData['unitShort']])) {
+ $fallbackUnit = [$diffIntervalData['unit'], $diffIntervalData['unitShort']];
+
+ break;
+ }
+ }
+
+ if (\count($interval) === 0) {
+ if ($relativeToNow && $options & CarbonInterface::JUST_NOW) {
+ $key = 'diff_now';
+ $translation = $this->translate($key, $interpolations, null, $translator);
+
+ if ($translation !== $key) {
+ return $translation;
+ }
+ }
+
+ $count = $options & CarbonInterface::NO_ZERO_DIFF ? 1 : 0;
+ $unit = $fallbackUnit[$short ? 1 : 0];
+ $interval[] = $this->translate($unit, $interpolations, $count, $translator, $altNumbers);
+ }
+
+ // join the interval parts by a space
+ $time = $join($interval);
+
+ unset($diffIntervalArray, $interval);
+
+ if ($absolute) {
+ return $time;
+ }
+
+ $isFuture = $this->invert === 1;
+
+ $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
+
+ if ($parts === 1) {
+ if ($relativeToNow && $unit === 'day') {
+ if ($count === 1 && $options & CarbonInterface::ONE_DAY_WORDS) {
+ $key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday';
+ $translation = $this->translate($key, $interpolations, null, $translator);
+
+ if ($translation !== $key) {
+ return $translation;
+ }
+ }
+
+ if ($count === 2 && $options & CarbonInterface::TWO_DAY_WORDS) {
+ $key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday';
+ $translation = $this->translate($key, $interpolations, null, $translator);
+
+ if ($translation !== $key) {
+ return $translation;
+ }
+ }
+ }
+
+ $aTime = $aUnit ? $handleDeclensions('a_'.$unit, $count) : null;
+
+ $time = $aTime ?: $handleDeclensions($unit, $count) ?: $time;
+ }
+
+ $time = [':time' => $time];
+
+ return $this->translate($transId, array_merge($time, $interpolations, $time), null, $translator);
+ }
+
+ /**
+ * Format the instance as a string using the forHumans() function.
+ *
+ * @throws Exception
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $format = $this->localToStringFormat;
+
+ if ($format) {
+ if ($format instanceof Closure) {
+ return $format($this);
+ }
+
+ return $this->format($format);
+ }
+
+ return $this->forHumans();
+ }
+
+ /**
+ * Return native DateInterval PHP object matching the current instance.
+ *
+ * @example
+ * ```
+ * var_dump(CarbonInterval::hours(2)->toDateInterval());
+ * ```
+ *
+ * @return DateInterval
+ */
+ public function toDateInterval()
+ {
+ return self::castIntervalToClass($this, DateInterval::class);
+ }
+
+ /**
+ * Convert the interval to a CarbonPeriod.
+ *
+ * @param array ...$params Start date, [end date or recurrences] and optional settings.
+ *
+ * @return CarbonPeriod
+ */
+ public function toPeriod(...$params)
+ {
+ return CarbonPeriod::create($this, ...$params);
+ }
+
+ /**
+ * Invert the interval.
+ *
+ * @param bool|int $inverted if a parameter is passed, the passed value casted as 1 or 0 is used
+ * as the new value of the ->invert property.
+ *
+ * @return $this
+ */
+ public function invert($inverted = null)
+ {
+ $this->invert = (\func_num_args() === 0 ? !$this->invert : $inverted) ? 1 : 0;
+
+ return $this;
+ }
+
+ protected function solveNegativeInterval()
+ {
+ if (!$this->isEmpty() && $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0 && $this->microseconds <= 0) {
+ $this->years *= -1;
+ $this->months *= -1;
+ $this->dayz *= -1;
+ $this->hours *= -1;
+ $this->minutes *= -1;
+ $this->seconds *= -1;
+ $this->microseconds *= -1;
+ $this->invert();
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add the passed interval to the current instance.
+ *
+ * @param string|DateInterval $unit
+ * @param int|float $value
+ *
+ * @return $this
+ */
+ public function add($unit, $value = 1)
+ {
+ if (is_numeric($unit)) {
+ [$value, $unit] = [$unit, $value];
+ }
+
+ if (\is_string($unit) && !preg_match('/^\s*\d/', $unit)) {
+ $unit = "$value $unit";
+ $value = 1;
+ }
+
+ $interval = static::make($unit);
+
+ if (!$interval) {
+ throw new InvalidIntervalException('This type of data cannot be added/subtracted.');
+ }
+
+ if ($value !== 1) {
+ $interval->times($value);
+ }
+
+ $sign = ($this->invert === 1) !== ($interval->invert === 1) ? -1 : 1;
+ $this->years += $interval->y * $sign;
+ $this->months += $interval->m * $sign;
+ $this->dayz += ($interval->days === false ? $interval->d : $interval->days) * $sign;
+ $this->hours += $interval->h * $sign;
+ $this->minutes += $interval->i * $sign;
+ $this->seconds += $interval->s * $sign;
+ $this->microseconds += $interval->microseconds * $sign;
+
+ $this->solveNegativeInterval();
+
+ return $this;
+ }
+
+ /**
+ * Subtract the passed interval to the current instance.
+ *
+ * @param string|DateInterval $unit
+ * @param int|float $value
+ *
+ * @return $this
+ */
+ public function sub($unit, $value = 1)
+ {
+ if (is_numeric($unit)) {
+ [$value, $unit] = [$unit, $value];
+ }
+
+ return $this->add($unit, -(float) $value);
+ }
+
+ /**
+ * Subtract the passed interval to the current instance.
+ *
+ * @param string|DateInterval $unit
+ * @param int|float $value
+ *
+ * @return $this
+ */
+ public function subtract($unit, $value = 1)
+ {
+ return $this->sub($unit, $value);
+ }
+
+ /**
+ * Add given parameters to the current interval.
+ *
+ * @param int $years
+ * @param int $months
+ * @param int|float $weeks
+ * @param int|float $days
+ * @param int|float $hours
+ * @param int|float $minutes
+ * @param int|float $seconds
+ * @param int|float $microseconds
+ *
+ * @return $this
+ */
+ public function plus(
+ $years = 0,
+ $months = 0,
+ $weeks = 0,
+ $days = 0,
+ $hours = 0,
+ $minutes = 0,
+ $seconds = 0,
+ $microseconds = 0
+ ): self {
+ return $this->add("
+ $years years $months months $weeks weeks $days days
+ $hours hours $minutes minutes $seconds seconds $microseconds microseconds
+ ");
+ }
+
+ /**
+ * Add given parameters to the current interval.
+ *
+ * @param int $years
+ * @param int $months
+ * @param int|float $weeks
+ * @param int|float $days
+ * @param int|float $hours
+ * @param int|float $minutes
+ * @param int|float $seconds
+ * @param int|float $microseconds
+ *
+ * @return $this
+ */
+ public function minus(
+ $years = 0,
+ $months = 0,
+ $weeks = 0,
+ $days = 0,
+ $hours = 0,
+ $minutes = 0,
+ $seconds = 0,
+ $microseconds = 0
+ ): self {
+ return $this->sub("
+ $years years $months months $weeks weeks $days days
+ $hours hours $minutes minutes $seconds seconds $microseconds microseconds
+ ");
+ }
+
+ /**
+ * Multiply current instance given number of times. times() is naive, it multiplies each unit
+ * (so day can be greater than 31, hour can be greater than 23, etc.) and the result is rounded
+ * separately for each unit.
+ *
+ * Use times() when you want a fast and approximated calculation that does not cascade units.
+ *
+ * For a precise and cascaded calculation,
+ *
+ * @see multiply()
+ *
+ * @param float|int $factor
+ *
+ * @return $this
+ */
+ public function times($factor)
+ {
+ if ($factor < 0) {
+ $this->invert = $this->invert ? 0 : 1;
+ $factor = -$factor;
+ }
+
+ $this->years = (int) round($this->years * $factor);
+ $this->months = (int) round($this->months * $factor);
+ $this->dayz = (int) round($this->dayz * $factor);
+ $this->hours = (int) round($this->hours * $factor);
+ $this->minutes = (int) round($this->minutes * $factor);
+ $this->seconds = (int) round($this->seconds * $factor);
+ $this->microseconds = (int) round($this->microseconds * $factor);
+
+ return $this;
+ }
+
+ /**
+ * Divide current instance by a given divider. shares() is naive, it divides each unit separately
+ * and the result is rounded for each unit. So 5 hours and 20 minutes shared by 3 becomes 2 hours
+ * and 7 minutes.
+ *
+ * Use shares() when you want a fast and approximated calculation that does not cascade units.
+ *
+ * For a precise and cascaded calculation,
+ *
+ * @see divide()
+ *
+ * @param float|int $divider
+ *
+ * @return $this
+ */
+ public function shares($divider)
+ {
+ return $this->times(1 / $divider);
+ }
+
+ protected function copyProperties(self $interval, $ignoreSign = false)
+ {
+ $this->years = $interval->years;
+ $this->months = $interval->months;
+ $this->dayz = $interval->dayz;
+ $this->hours = $interval->hours;
+ $this->minutes = $interval->minutes;
+ $this->seconds = $interval->seconds;
+ $this->microseconds = $interval->microseconds;
+
+ if (!$ignoreSign) {
+ $this->invert = $interval->invert;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Multiply and cascade current instance by a given factor.
+ *
+ * @param float|int $factor
+ *
+ * @return $this
+ */
+ public function multiply($factor)
+ {
+ if ($factor < 0) {
+ $this->invert = $this->invert ? 0 : 1;
+ $factor = -$factor;
+ }
+
+ $yearPart = (int) floor($this->years * $factor); // Split calculation to prevent imprecision
+
+ if ($yearPart) {
+ $this->years -= $yearPart / $factor;
+ }
+
+ return $this->copyProperties(
+ static::create($yearPart)
+ ->microseconds(abs($this->totalMicroseconds) * $factor)
+ ->cascade(),
+ true
+ );
+ }
+
+ /**
+ * Divide and cascade current instance by a given divider.
+ *
+ * @param float|int $divider
+ *
+ * @return $this
+ */
+ public function divide($divider)
+ {
+ return $this->multiply(1 / $divider);
+ }
+
+ /**
+ * Get the interval_spec string of a date interval.
+ *
+ * @param DateInterval $interval
+ *
+ * @return string
+ */
+ public static function getDateIntervalSpec(DateInterval $interval)
+ {
+ $date = array_filter([
+ static::PERIOD_YEARS => abs($interval->y),
+ static::PERIOD_MONTHS => abs($interval->m),
+ static::PERIOD_DAYS => abs($interval->d),
+ ]);
+
+ $time = array_filter([
+ static::PERIOD_HOURS => abs($interval->h),
+ static::PERIOD_MINUTES => abs($interval->i),
+ static::PERIOD_SECONDS => abs($interval->s),
+ ]);
+
+ $specString = static::PERIOD_PREFIX;
+
+ foreach ($date as $key => $value) {
+ $specString .= $value.$key;
+ }
+
+ if (\count($time) > 0) {
+ $specString .= static::PERIOD_TIME_PREFIX;
+ foreach ($time as $key => $value) {
+ $specString .= $value.$key;
+ }
+ }
+
+ return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString;
+ }
+
+ /**
+ * Get the interval_spec string.
+ *
+ * @return string
+ */
+ public function spec()
+ {
+ return static::getDateIntervalSpec($this);
+ }
+
+ /**
+ * Comparing 2 date intervals.
+ *
+ * @param DateInterval $first
+ * @param DateInterval $second
+ *
+ * @return int
+ */
+ public static function compareDateIntervals(DateInterval $first, DateInterval $second)
+ {
+ $current = Carbon::now();
+ $passed = $current->avoidMutation()->add($second);
+ $current->add($first);
+
+ if ($current < $passed) {
+ return -1;
+ }
+ if ($current > $passed) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Comparing with passed interval.
+ *
+ * @param DateInterval $interval
+ *
+ * @return int
+ */
+ public function compare(DateInterval $interval)
+ {
+ return static::compareDateIntervals($this, $interval);
+ }
+
+ private function invertCascade(array $values)
+ {
+ return $this->set(array_map(function ($value) {
+ return -$value;
+ }, $values))->doCascade(true)->invert();
+ }
+
+ private function doCascade(bool $deep)
+ {
+ $originalData = $this->toArray();
+ $originalData['milliseconds'] = (int) ($originalData['microseconds'] / static::getMicrosecondsPerMillisecond());
+ $originalData['microseconds'] = $originalData['microseconds'] % static::getMicrosecondsPerMillisecond();
+ $originalData['daysExcludeWeeks'] = $originalData['days'];
+ unset($originalData['days']);
+ $newData = $originalData;
+
+ foreach (static::getFlipCascadeFactors() as $source => [$target, $factor]) {
+ foreach (['source', 'target'] as $key) {
+ if ($$key === 'dayz') {
+ $$key = 'daysExcludeWeeks';
+ }
+ }
+
+ $value = $newData[$source];
+ $modulo = ($factor + ($value % $factor)) % $factor;
+ $newData[$source] = $modulo;
+ $newData[$target] += ($value - $modulo) / $factor;
+ }
+
+ $positive = null;
+
+ if (!$deep) {
+ foreach ($newData as $value) {
+ if ($value) {
+ if ($positive === null) {
+ $positive = ($value > 0);
+
+ continue;
+ }
+
+ if (($value > 0) !== $positive) {
+ return $this->invertCascade($originalData)
+ ->solveNegativeInterval();
+ }
+ }
+ }
+ }
+
+ return $this->set($newData)
+ ->solveNegativeInterval();
+ }
+
+ /**
+ * Convert overflowed values into bigger units.
+ *
+ * @return $this
+ */
+ public function cascade()
+ {
+ return $this->doCascade(false);
+ }
+
+ public function hasNegativeValues(): bool
+ {
+ foreach ($this->toArray() as $value) {
+ if ($value < 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function hasPositiveValues(): bool
+ {
+ foreach ($this->toArray() as $value) {
+ if ($value > 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get amount of given unit equivalent to the interval.
+ *
+ * @param string $unit
+ *
+ * @throws UnknownUnitException|UnitNotConfiguredException
+ *
+ * @return float
+ */
+ public function total($unit)
+ {
+ $realUnit = $unit = strtolower($unit);
+
+ if (\in_array($unit, ['days', 'weeks'])) {
+ $realUnit = 'dayz';
+ } elseif (!\in_array($unit, ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) {
+ throw new UnknownUnitException($unit);
+ }
+
+ $result = 0;
+ $cumulativeFactor = 0;
+ $unitFound = false;
+ $factors = static::getFlipCascadeFactors();
+ $daysPerWeek = static::getDaysPerWeek();
+
+ $values = [
+ 'years' => $this->years,
+ 'months' => $this->months,
+ 'weeks' => (int) ($this->d / $daysPerWeek),
+ 'dayz' => $this->d % $daysPerWeek,
+ 'hours' => $this->hours,
+ 'minutes' => $this->minutes,
+ 'seconds' => $this->seconds,
+ 'milliseconds' => (int) ($this->microseconds / Carbon::MICROSECONDS_PER_MILLISECOND),
+ 'microseconds' => $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND,
+ ];
+
+ if (isset($factors['dayz']) && $factors['dayz'][0] !== 'weeks') {
+ $values['dayz'] += $values['weeks'] * $daysPerWeek;
+ $values['weeks'] = 0;
+ }
+
+ foreach ($factors as $source => [$target, $factor]) {
+ if ($source === $realUnit) {
+ $unitFound = true;
+ $value = $values[$source];
+ $result += $value;
+ $cumulativeFactor = 1;
+ }
+
+ if ($factor === false) {
+ if ($unitFound) {
+ break;
+ }
+
+ $result = 0;
+ $cumulativeFactor = 0;
+
+ continue;
+ }
+
+ if ($target === $realUnit) {
+ $unitFound = true;
+ }
+
+ if ($cumulativeFactor) {
+ $cumulativeFactor *= $factor;
+ $result += $values[$target] * $cumulativeFactor;
+
+ continue;
+ }
+
+ $value = $values[$source];
+
+ $result = ($result + $value) / $factor;
+ }
+
+ if (isset($target) && !$cumulativeFactor) {
+ $result += $values[$target];
+ }
+
+ if (!$unitFound) {
+ throw new UnitNotConfiguredException($unit);
+ }
+
+ if ($this->invert) {
+ $result *= -1;
+ }
+
+ if ($unit === 'weeks') {
+ return $result / $daysPerWeek;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Determines if the instance is equal to another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @see equalTo()
+ *
+ * @return bool
+ */
+ public function eq($interval): bool
+ {
+ return $this->equalTo($interval);
+ }
+
+ /**
+ * Determines if the instance is equal to another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @return bool
+ */
+ public function equalTo($interval): bool
+ {
+ $interval = $this->resolveInterval($interval);
+
+ return $interval !== null && $this->totalMicroseconds === $interval->totalMicroseconds;
+ }
+
+ /**
+ * Determines if the instance is not equal to another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @see notEqualTo()
+ *
+ * @return bool
+ */
+ public function ne($interval): bool
+ {
+ return $this->notEqualTo($interval);
+ }
+
+ /**
+ * Determines if the instance is not equal to another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @return bool
+ */
+ public function notEqualTo($interval): bool
+ {
+ return !$this->eq($interval);
+ }
+
+ /**
+ * Determines if the instance is greater (longer) than another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @see greaterThan()
+ *
+ * @return bool
+ */
+ public function gt($interval): bool
+ {
+ return $this->greaterThan($interval);
+ }
+
+ /**
+ * Determines if the instance is greater (longer) than another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @return bool
+ */
+ public function greaterThan($interval): bool
+ {
+ $interval = $this->resolveInterval($interval);
+
+ return $interval === null || $this->totalMicroseconds > $interval->totalMicroseconds;
+ }
+
+ /**
+ * Determines if the instance is greater (longer) than or equal to another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @see greaterThanOrEqualTo()
+ *
+ * @return bool
+ */
+ public function gte($interval): bool
+ {
+ return $this->greaterThanOrEqualTo($interval);
+ }
+
+ /**
+ * Determines if the instance is greater (longer) than or equal to another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @return bool
+ */
+ public function greaterThanOrEqualTo($interval): bool
+ {
+ return $this->greaterThan($interval) || $this->equalTo($interval);
+ }
+
+ /**
+ * Determines if the instance is less (shorter) than another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @see lessThan()
+ *
+ * @return bool
+ */
+ public function lt($interval): bool
+ {
+ return $this->lessThan($interval);
+ }
+
+ /**
+ * Determines if the instance is less (shorter) than another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @return bool
+ */
+ public function lessThan($interval): bool
+ {
+ $interval = $this->resolveInterval($interval);
+
+ return $interval !== null && $this->totalMicroseconds < $interval->totalMicroseconds;
+ }
+
+ /**
+ * Determines if the instance is less (shorter) than or equal to another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @see lessThanOrEqualTo()
+ *
+ * @return bool
+ */
+ public function lte($interval): bool
+ {
+ return $this->lessThanOrEqualTo($interval);
+ }
+
+ /**
+ * Determines if the instance is less (shorter) than or equal to another
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval
+ *
+ * @return bool
+ */
+ public function lessThanOrEqualTo($interval): bool
+ {
+ return $this->lessThan($interval) || $this->equalTo($interval);
+ }
+
+ /**
+ * Determines if the instance is between two others.
+ *
+ * The third argument allow you to specify if bounds are included or not (true by default)
+ * but for when you including/excluding bounds may produce different results in your application,
+ * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead.
+ *
+ * @example
+ * ```
+ * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(3)); // true
+ * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::hours(36)); // false
+ * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2)); // true
+ * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2), false); // false
+ * ```
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval1
+ * @param CarbonInterval|DateInterval|mixed $interval2
+ * @param bool $equal Indicates if an equal to comparison should be done
+ *
+ * @return bool
+ */
+ public function between($interval1, $interval2, $equal = true): bool
+ {
+ return $equal
+ ? $this->greaterThanOrEqualTo($interval1) && $this->lessThanOrEqualTo($interval2)
+ : $this->greaterThan($interval1) && $this->lessThan($interval2);
+ }
+
+ /**
+ * Determines if the instance is between two others, bounds excluded.
+ *
+ * @example
+ * ```
+ * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
+ * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
+ * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // true
+ * ```
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval1
+ * @param CarbonInterval|DateInterval|mixed $interval2
+ *
+ * @return bool
+ */
+ public function betweenIncluded($interval1, $interval2): bool
+ {
+ return $this->between($interval1, $interval2, true);
+ }
+
+ /**
+ * Determines if the instance is between two others, bounds excluded.
+ *
+ * @example
+ * ```
+ * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
+ * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
+ * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // false
+ * ```
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval1
+ * @param CarbonInterval|DateInterval|mixed $interval2
+ *
+ * @return bool
+ */
+ public function betweenExcluded($interval1, $interval2): bool
+ {
+ return $this->between($interval1, $interval2, false);
+ }
+
+ /**
+ * Determines if the instance is between two others
+ *
+ * @example
+ * ```
+ * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(3)); // true
+ * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::hours(36)); // false
+ * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2)); // true
+ * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2), false); // false
+ * ```
+ *
+ * @param CarbonInterval|DateInterval|mixed $interval1
+ * @param CarbonInterval|DateInterval|mixed $interval2
+ * @param bool $equal Indicates if an equal to comparison should be done
+ *
+ * @return bool
+ */
+ public function isBetween($interval1, $interval2, $equal = true): bool
+ {
+ return $this->between($interval1, $interval2, $equal);
+ }
+
+ /**
+ * Round the current instance at the given unit with given precision if specified and the given function.
+ *
+ * @param string $unit
+ * @param float|int|string|DateInterval|null $precision
+ * @param string $function
+ *
+ * @throws Exception
+ *
+ * @return $this
+ */
+ public function roundUnit($unit, $precision = 1, $function = 'round')
+ {
+ $base = CarbonImmutable::parse('2000-01-01 00:00:00', 'UTC')
+ ->roundUnit($unit, $precision, $function);
+ $next = $base->add($this);
+ $inverted = $next < $base;
+
+ if ($inverted) {
+ $next = $base->sub($this);
+ }
+
+ $this->copyProperties(
+ $next
+ ->roundUnit($unit, $precision, $function)
+ ->diffAsCarbonInterval($base)
+ );
+
+ return $this->invert($inverted);
+ }
+
+ /**
+ * Truncate the current instance at the given unit with given precision if specified.
+ *
+ * @param string $unit
+ * @param float|int|string|DateInterval|null $precision
+ *
+ * @throws Exception
+ *
+ * @return $this
+ */
+ public function floorUnit($unit, $precision = 1)
+ {
+ return $this->roundUnit($unit, $precision, 'floor');
+ }
+
+ /**
+ * Ceil the current instance at the given unit with given precision if specified.
+ *
+ * @param string $unit
+ * @param float|int|string|DateInterval|null $precision
+ *
+ * @throws Exception
+ *
+ * @return $this
+ */
+ public function ceilUnit($unit, $precision = 1)
+ {
+ return $this->roundUnit($unit, $precision, 'ceil');
+ }
+
+ /**
+ * Round the current instance second with given precision if specified.
+ *
+ * @param float|int|string|DateInterval|null $precision
+ * @param string $function
+ *
+ * @throws Exception
+ *
+ * @return $this
+ */
+ public function round($precision = 1, $function = 'round')
+ {
+ return $this->roundWith($precision, $function);
+ }
+
+ /**
+ * Round the current instance second with given precision if specified.
+ *
+ * @param float|int|string|DateInterval|null $precision
+ *
+ * @throws Exception
+ *
+ * @return $this
+ */
+ public function floor($precision = 1)
+ {
+ return $this->round($precision, 'floor');
+ }
+
+ /**
+ * Ceil the current instance second with given precision if specified.
+ *
+ * @param float|int|string|DateInterval|null $precision
+ *
+ * @throws Exception
+ *
+ * @return $this
+ */
+ public function ceil($precision = 1)
+ {
+ return $this->round($precision, 'ceil');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php
new file mode 100644
index 0000000..70e6ba4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php
@@ -0,0 +1,2498 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use Carbon\Exceptions\InvalidCastException;
+use Carbon\Exceptions\InvalidIntervalException;
+use Carbon\Exceptions\InvalidPeriodDateException;
+use Carbon\Exceptions\InvalidPeriodParameterException;
+use Carbon\Exceptions\NotACarbonClassException;
+use Carbon\Exceptions\NotAPeriodException;
+use Carbon\Exceptions\UnknownGetterException;
+use Carbon\Exceptions\UnknownMethodException;
+use Carbon\Exceptions\UnreachableException;
+use Carbon\Traits\IntervalRounding;
+use Carbon\Traits\Mixin;
+use Carbon\Traits\Options;
+use Closure;
+use Countable;
+use DateInterval;
+use DatePeriod;
+use DateTime;
+use DateTimeInterface;
+use InvalidArgumentException;
+use Iterator;
+use JsonSerializable;
+use ReflectionException;
+use ReturnTypeWillChange;
+use RuntimeException;
+
+/**
+ * Substitution of DatePeriod with some modifications and many more features.
+ *
+ * @property-read int|float $recurrences number of recurrences (if end not set).
+ * @property-read bool $include_start_date rather the start date is included in the iteration.
+ * @property-read bool $include_end_date rather the end date is included in the iteration (if recurrences not set).
+ * @property-read CarbonInterface $start Period start date.
+ * @property-read CarbonInterface $current Current date from the iteration.
+ * @property-read CarbonInterface $end Period end date.
+ * @property-read CarbonInterval $interval Underlying date interval instance. Always present, one day by default.
+ *
+ * @method static CarbonPeriod start($date, $inclusive = null) Create instance specifying start date or modify the start date if called on an instance.
+ * @method static CarbonPeriod since($date, $inclusive = null) Alias for start().
+ * @method static CarbonPeriod sinceNow($inclusive = null) Create instance with start date set to now or set the start date to now if called on an instance.
+ * @method static CarbonPeriod end($date = null, $inclusive = null) Create instance specifying end date or modify the end date if called on an instance.
+ * @method static CarbonPeriod until($date = null, $inclusive = null) Alias for end().
+ * @method static CarbonPeriod untilNow($inclusive = null) Create instance with end date set to now or set the end date to now if called on an instance.
+ * @method static CarbonPeriod dates($start, $end = null) Create instance with start and end dates or modify the start and end dates if called on an instance.
+ * @method static CarbonPeriod between($start, $end = null) Create instance with start and end dates or modify the start and end dates if called on an instance.
+ * @method static CarbonPeriod recurrences($recurrences = null) Create instance with maximum number of recurrences or modify the number of recurrences if called on an instance.
+ * @method static CarbonPeriod times($recurrences = null) Alias for recurrences().
+ * @method static CarbonPeriod options($options = null) Create instance with options or modify the options if called on an instance.
+ * @method static CarbonPeriod toggle($options, $state = null) Create instance with options toggled on or off, or toggle options if called on an instance.
+ * @method static CarbonPeriod filter($callback, $name = null) Create instance with filter added to the stack or append a filter if called on an instance.
+ * @method static CarbonPeriod push($callback, $name = null) Alias for filter().
+ * @method static CarbonPeriod prepend($callback, $name = null) Create instance with filter prepended to the stack or prepend a filter if called on an instance.
+ * @method static CarbonPeriod filters(array $filters = []) Create instance with filters stack or replace the whole filters stack if called on an instance.
+ * @method static CarbonPeriod interval($interval) Create instance with given date interval or modify the interval if called on an instance.
+ * @method static CarbonPeriod each($interval) Create instance with given date interval or modify the interval if called on an instance.
+ * @method static CarbonPeriod every($interval) Create instance with given date interval or modify the interval if called on an instance.
+ * @method static CarbonPeriod step($interval) Create instance with given date interval or modify the interval if called on an instance.
+ * @method static CarbonPeriod stepBy($interval) Create instance with given date interval or modify the interval if called on an instance.
+ * @method static CarbonPeriod invert() Create instance with inverted date interval or invert the interval if called on an instance.
+ * @method static CarbonPeriod years($years = 1) Create instance specifying a number of years for date interval or replace the interval by the given a number of years if called on an instance.
+ * @method static CarbonPeriod year($years = 1) Alias for years().
+ * @method static CarbonPeriod months($months = 1) Create instance specifying a number of months for date interval or replace the interval by the given a number of months if called on an instance.
+ * @method static CarbonPeriod month($months = 1) Alias for months().
+ * @method static CarbonPeriod weeks($weeks = 1) Create instance specifying a number of weeks for date interval or replace the interval by the given a number of weeks if called on an instance.
+ * @method static CarbonPeriod week($weeks = 1) Alias for weeks().
+ * @method static CarbonPeriod days($days = 1) Create instance specifying a number of days for date interval or replace the interval by the given a number of days if called on an instance.
+ * @method static CarbonPeriod dayz($days = 1) Alias for days().
+ * @method static CarbonPeriod day($days = 1) Alias for days().
+ * @method static CarbonPeriod hours($hours = 1) Create instance specifying a number of hours for date interval or replace the interval by the given a number of hours if called on an instance.
+ * @method static CarbonPeriod hour($hours = 1) Alias for hours().
+ * @method static CarbonPeriod minutes($minutes = 1) Create instance specifying a number of minutes for date interval or replace the interval by the given a number of minutes if called on an instance.
+ * @method static CarbonPeriod minute($minutes = 1) Alias for minutes().
+ * @method static CarbonPeriod seconds($seconds = 1) Create instance specifying a number of seconds for date interval or replace the interval by the given a number of seconds if called on an instance.
+ * @method static CarbonPeriod second($seconds = 1) Alias for seconds().
+ * @method $this roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method $this roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method $this floorYear(float $precision = 1) Truncate the current instance year with given precision.
+ * @method $this floorYears(float $precision = 1) Truncate the current instance year with given precision.
+ * @method $this ceilYear(float $precision = 1) Ceil the current instance year with given precision.
+ * @method $this ceilYears(float $precision = 1) Ceil the current instance year with given precision.
+ * @method $this roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method $this roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method $this floorMonth(float $precision = 1) Truncate the current instance month with given precision.
+ * @method $this floorMonths(float $precision = 1) Truncate the current instance month with given precision.
+ * @method $this ceilMonth(float $precision = 1) Ceil the current instance month with given precision.
+ * @method $this ceilMonths(float $precision = 1) Ceil the current instance month with given precision.
+ * @method $this roundWeek(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method $this roundWeeks(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method $this floorWeek(float $precision = 1) Truncate the current instance day with given precision.
+ * @method $this floorWeeks(float $precision = 1) Truncate the current instance day with given precision.
+ * @method $this ceilWeek(float $precision = 1) Ceil the current instance day with given precision.
+ * @method $this ceilWeeks(float $precision = 1) Ceil the current instance day with given precision.
+ * @method $this roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method $this roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method $this floorDay(float $precision = 1) Truncate the current instance day with given precision.
+ * @method $this floorDays(float $precision = 1) Truncate the current instance day with given precision.
+ * @method $this ceilDay(float $precision = 1) Ceil the current instance day with given precision.
+ * @method $this ceilDays(float $precision = 1) Ceil the current instance day with given precision.
+ * @method $this roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method $this roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method $this floorHour(float $precision = 1) Truncate the current instance hour with given precision.
+ * @method $this floorHours(float $precision = 1) Truncate the current instance hour with given precision.
+ * @method $this ceilHour(float $precision = 1) Ceil the current instance hour with given precision.
+ * @method $this ceilHours(float $precision = 1) Ceil the current instance hour with given precision.
+ * @method $this roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method $this roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method $this floorMinute(float $precision = 1) Truncate the current instance minute with given precision.
+ * @method $this floorMinutes(float $precision = 1) Truncate the current instance minute with given precision.
+ * @method $this ceilMinute(float $precision = 1) Ceil the current instance minute with given precision.
+ * @method $this ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision.
+ * @method $this roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method $this roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method $this floorSecond(float $precision = 1) Truncate the current instance second with given precision.
+ * @method $this floorSeconds(float $precision = 1) Truncate the current instance second with given precision.
+ * @method $this ceilSecond(float $precision = 1) Ceil the current instance second with given precision.
+ * @method $this ceilSeconds(float $precision = 1) Ceil the current instance second with given precision.
+ * @method $this roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method $this roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method $this floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method $this floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method $this ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method $this ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method $this roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method $this roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method $this floorCentury(float $precision = 1) Truncate the current instance century with given precision.
+ * @method $this floorCenturies(float $precision = 1) Truncate the current instance century with given precision.
+ * @method $this ceilCentury(float $precision = 1) Ceil the current instance century with given precision.
+ * @method $this ceilCenturies(float $precision = 1) Ceil the current instance century with given precision.
+ * @method $this roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method $this roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method $this floorDecade(float $precision = 1) Truncate the current instance decade with given precision.
+ * @method $this floorDecades(float $precision = 1) Truncate the current instance decade with given precision.
+ * @method $this ceilDecade(float $precision = 1) Ceil the current instance decade with given precision.
+ * @method $this ceilDecades(float $precision = 1) Ceil the current instance decade with given precision.
+ * @method $this roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method $this roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method $this floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method $this floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method $this ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method $this ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method $this roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method $this roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method $this floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method $this floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method $this ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method $this ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method $this roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method $this roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method $this floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method $this floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method $this ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision.
+ * @method $this ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision.
+ */
+class CarbonPeriod implements Iterator, Countable, JsonSerializable
+{
+ use IntervalRounding;
+ use Mixin {
+ Mixin::mixin as baseMixin;
+ }
+ use Options;
+
+ /**
+ * Built-in filters.
+ *
+ * @var string
+ */
+ public const RECURRENCES_FILTER = [self::class, 'filterRecurrences'];
+ public const END_DATE_FILTER = [self::class, 'filterEndDate'];
+
+ /**
+ * Special value which can be returned by filters to end iteration. Also a filter.
+ *
+ * @var string
+ */
+ public const END_ITERATION = [self::class, 'endIteration'];
+
+ /**
+ * Exclude start date from iteration.
+ *
+ * @var int
+ */
+ public const EXCLUDE_START_DATE = 1;
+
+ /**
+ * Exclude end date from iteration.
+ *
+ * @var int
+ */
+ public const EXCLUDE_END_DATE = 2;
+
+ /**
+ * Yield CarbonImmutable instances.
+ *
+ * @var int
+ */
+ public const IMMUTABLE = 4;
+
+ /**
+ * Number of maximum attempts before giving up on finding next valid date.
+ *
+ * @var int
+ */
+ public const NEXT_MAX_ATTEMPTS = 1000;
+
+ /**
+ * Number of maximum attempts before giving up on finding end date.
+ *
+ * @var int
+ */
+ public const END_MAX_ATTEMPTS = 10000;
+
+ /**
+ * The registered macros.
+ *
+ * @var array
+ */
+ protected static $macros = [];
+
+ /**
+ * Date class of iteration items.
+ *
+ * @var string
+ */
+ protected $dateClass = Carbon::class;
+
+ /**
+ * Underlying date interval instance. Always present, one day by default.
+ *
+ * @var CarbonInterval
+ */
+ protected $dateInterval;
+
+ /**
+ * Whether current date interval was set by default.
+ *
+ * @var bool
+ */
+ protected $isDefaultInterval;
+
+ /**
+ * The filters stack.
+ *
+ * @var array
+ */
+ protected $filters = [];
+
+ /**
+ * Period start date. Applied on rewind. Always present, now by default.
+ *
+ * @var CarbonInterface
+ */
+ protected $startDate;
+
+ /**
+ * Period end date. For inverted interval should be before the start date. Applied via a filter.
+ *
+ * @var CarbonInterface|null
+ */
+ protected $endDate;
+
+ /**
+ * Limit for number of recurrences. Applied via a filter.
+ *
+ * @var int|null
+ */
+ protected $recurrences;
+
+ /**
+ * Iteration options.
+ *
+ * @var int
+ */
+ protected $options;
+
+ /**
+ * Index of current date. Always sequential, even if some dates are skipped by filters.
+ * Equal to null only before the first iteration.
+ *
+ * @var int
+ */
+ protected $key;
+
+ /**
+ * Current date. May temporarily hold unaccepted value when looking for a next valid date.
+ * Equal to null only before the first iteration.
+ *
+ * @var CarbonInterface
+ */
+ protected $current;
+
+ /**
+ * Timezone of current date. Taken from the start date.
+ *
+ * @var \DateTimeZone|null
+ */
+ protected $timezone;
+
+ /**
+ * The cached validation result for current date.
+ *
+ * @var bool|string|null
+ */
+ protected $validationResult;
+
+ /**
+ * Timezone handler for settings() method.
+ *
+ * @var mixed
+ */
+ protected $tzName;
+
+ /**
+ * Make a CarbonPeriod instance from given variable if possible.
+ *
+ * @param mixed $var
+ *
+ * @return static|null
+ */
+ public static function make($var)
+ {
+ try {
+ return static::instance($var);
+ } catch (NotAPeriodException $e) {
+ return static::create($var);
+ }
+ }
+
+ /**
+ * Create a new instance from a DatePeriod or CarbonPeriod object.
+ *
+ * @param CarbonPeriod|DatePeriod $period
+ *
+ * @return static
+ */
+ public static function instance($period)
+ {
+ if ($period instanceof static) {
+ return $period->copy();
+ }
+
+ if ($period instanceof self) {
+ return new static(
+ $period->getStartDate(),
+ $period->getEndDate() ?: $period->getRecurrences(),
+ $period->getDateInterval(),
+ $period->getOptions()
+ );
+ }
+
+ if ($period instanceof DatePeriod) {
+ return new static(
+ $period->start,
+ $period->end ?: ($period->recurrences - 1),
+ $period->interval,
+ $period->include_start_date ? 0 : static::EXCLUDE_START_DATE
+ );
+ }
+
+ $class = \get_called_class();
+ $type = \gettype($period);
+
+ throw new NotAPeriodException(
+ 'Argument 1 passed to '.$class.'::'.__METHOD__.'() '.
+ 'must be an instance of DatePeriod or '.$class.', '.
+ ($type === 'object' ? 'instance of '.\get_class($period) : $type).' given.'
+ );
+ }
+
+ /**
+ * Create a new instance.
+ *
+ * @return static
+ */
+ public static function create(...$params)
+ {
+ return static::createFromArray($params);
+ }
+
+ /**
+ * Create a new instance from an array of parameters.
+ *
+ * @param array $params
+ *
+ * @return static
+ */
+ public static function createFromArray(array $params)
+ {
+ return new static(...$params);
+ }
+
+ /**
+ * Create CarbonPeriod from ISO 8601 string.
+ *
+ * @param string $iso
+ * @param int|null $options
+ *
+ * @return static
+ */
+ public static function createFromIso($iso, $options = null)
+ {
+ $params = static::parseIso8601($iso);
+
+ $instance = static::createFromArray($params);
+
+ if ($options !== null) {
+ $instance->setOptions($options);
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Return whether given interval contains non zero value of any time unit.
+ *
+ * @param \DateInterval $interval
+ *
+ * @return bool
+ */
+ protected static function intervalHasTime(DateInterval $interval)
+ {
+ return $interval->h || $interval->i || $interval->s || $interval->f;
+ }
+
+ /**
+ * Return whether given variable is an ISO 8601 specification.
+ *
+ * Note: Check is very basic, as actual validation will be done later when parsing.
+ * We just want to ensure that variable is not any other type of a valid parameter.
+ *
+ * @param mixed $var
+ *
+ * @return bool
+ */
+ protected static function isIso8601($var)
+ {
+ if (!\is_string($var)) {
+ return false;
+ }
+
+ // Match slash but not within a timezone name.
+ $part = '[a-z]+(?:[_-][a-z]+)*';
+
+ preg_match("#\b$part/$part\b|(/)#i", $var, $match);
+
+ return isset($match[1]);
+ }
+
+ /**
+ * Parse given ISO 8601 string into an array of arguments.
+ *
+ * @SuppressWarnings(PHPMD.ElseExpression)
+ *
+ * @param string $iso
+ *
+ * @return array
+ */
+ protected static function parseIso8601($iso)
+ {
+ $result = [];
+
+ $interval = null;
+ $start = null;
+ $end = null;
+
+ foreach (explode('/', $iso) as $key => $part) {
+ if ($key === 0 && preg_match('/^R([0-9]*)$/', $part, $match)) {
+ $parsed = \strlen($match[1]) ? (int) $match[1] : null;
+ } elseif ($interval === null && $parsed = CarbonInterval::make($part)) {
+ $interval = $part;
+ } elseif ($start === null && $parsed = Carbon::make($part)) {
+ $start = $part;
+ } elseif ($end === null && $parsed = Carbon::make(static::addMissingParts($start ?? '', $part))) {
+ $end = $part;
+ } else {
+ throw new InvalidPeriodParameterException("Invalid ISO 8601 specification: $iso.");
+ }
+
+ $result[] = $parsed;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Add missing parts of the target date from the soure date.
+ *
+ * @param string $source
+ * @param string $target
+ *
+ * @return string
+ */
+ protected static function addMissingParts($source, $target)
+ {
+ $pattern = '/'.preg_replace('/[0-9]+/', '[0-9]+', preg_quote($target, '/')).'$/';
+
+ $result = preg_replace($pattern, $target, $source, 1, $count);
+
+ return $count ? $result : $target;
+ }
+
+ /**
+ * Register a custom macro.
+ *
+ * @example
+ * ```
+ * CarbonPeriod::macro('middle', function () {
+ * return $this->getStartDate()->average($this->getEndDate());
+ * });
+ * echo CarbonPeriod::since('2011-05-12')->until('2011-06-03')->middle();
+ * ```
+ *
+ * @param string $name
+ * @param object|callable $macro
+ *
+ * @return void
+ */
+ public static function macro($name, $macro)
+ {
+ static::$macros[$name] = $macro;
+ }
+
+ /**
+ * Register macros from a mixin object.
+ *
+ * @example
+ * ```
+ * CarbonPeriod::mixin(new class {
+ * public function addDays() {
+ * return function ($count = 1) {
+ * return $this->setStartDate(
+ * $this->getStartDate()->addDays($count)
+ * )->setEndDate(
+ * $this->getEndDate()->addDays($count)
+ * );
+ * };
+ * }
+ * public function subDays() {
+ * return function ($count = 1) {
+ * return $this->setStartDate(
+ * $this->getStartDate()->subDays($count)
+ * )->setEndDate(
+ * $this->getEndDate()->subDays($count)
+ * );
+ * };
+ * }
+ * });
+ * echo CarbonPeriod::create('2000-01-01', '2000-02-01')->addDays(5)->subDays(3);
+ * ```
+ *
+ * @param object|string $mixin
+ *
+ * @throws ReflectionException
+ *
+ * @return void
+ */
+ public static function mixin($mixin)
+ {
+ static::baseMixin($mixin);
+ }
+
+ /**
+ * Check if macro is registered.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public static function hasMacro($name)
+ {
+ return isset(static::$macros[$name]);
+ }
+
+ /**
+ * Provide static proxy for instance aliases.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public static function __callStatic($method, $parameters)
+ {
+ $date = new static();
+
+ if (static::hasMacro($method)) {
+ return static::bindMacroContext(null, function () use (&$method, &$parameters, &$date) {
+ return $date->callMacro($method, $parameters);
+ });
+ }
+
+ return $date->$method(...$parameters);
+ }
+
+ /**
+ * CarbonPeriod constructor.
+ *
+ * @SuppressWarnings(PHPMD.ElseExpression)
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct(...$arguments)
+ {
+ // Parse and assign arguments one by one. First argument may be an ISO 8601 spec,
+ // which will be first parsed into parts and then processed the same way.
+
+ $argumentsCount = \count($arguments);
+
+ if ($argumentsCount && static::isIso8601($iso = $arguments[0])) {
+ array_splice($arguments, 0, 1, static::parseIso8601($iso));
+ }
+
+ if ($argumentsCount === 1) {
+ if ($arguments[0] instanceof DatePeriod) {
+ $arguments = [
+ $arguments[0]->start,
+ $arguments[0]->end ?: ($arguments[0]->recurrences - 1),
+ $arguments[0]->interval,
+ $arguments[0]->include_start_date ? 0 : static::EXCLUDE_START_DATE,
+ ];
+ } elseif ($arguments[0] instanceof self) {
+ $arguments = [
+ $arguments[0]->getStartDate(),
+ $arguments[0]->getEndDate() ?: $arguments[0]->getRecurrences(),
+ $arguments[0]->getDateInterval(),
+ $arguments[0]->getOptions(),
+ ];
+ }
+ }
+
+ foreach ($arguments as $argument) {
+ if ($this->dateInterval === null &&
+ (
+ \is_string($argument) && preg_match(
+ '/^(-?\d(\d(?![\/-])|[^\d\/-]([\/-])?)*|P[T0-9].*|(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+)$/i',
+ $argument
+ ) ||
+ $argument instanceof DateInterval ||
+ $argument instanceof Closure
+ ) &&
+ $parsed = @CarbonInterval::make($argument)
+ ) {
+ $this->setDateInterval($parsed);
+ } elseif ($this->startDate === null && $parsed = Carbon::make($argument)) {
+ $this->setStartDate($parsed);
+ } elseif ($this->endDate === null && $parsed = Carbon::make($argument)) {
+ $this->setEndDate($parsed);
+ } elseif ($this->recurrences === null && $this->endDate === null && is_numeric($argument)) {
+ $this->setRecurrences($argument);
+ } elseif ($this->options === null && (\is_int($argument) || $argument === null)) {
+ $this->setOptions($argument);
+ } else {
+ throw new InvalidPeriodParameterException('Invalid constructor parameters.');
+ }
+ }
+
+ if ($this->startDate === null) {
+ $this->setStartDate(Carbon::now());
+ }
+
+ if ($this->dateInterval === null) {
+ $this->setDateInterval(CarbonInterval::day());
+
+ $this->isDefaultInterval = true;
+ }
+
+ if ($this->options === null) {
+ $this->setOptions(0);
+ }
+ }
+
+ /**
+ * Get a copy of the instance.
+ *
+ * @return static
+ */
+ public function copy()
+ {
+ return clone $this;
+ }
+
+ /**
+ * Get the getter for a property allowing both `DatePeriod` snakeCase and camelCase names.
+ *
+ * @param string $name
+ *
+ * @return callable|null
+ */
+ protected function getGetter(string $name)
+ {
+ switch (strtolower(preg_replace('/[A-Z]/', '_$0', $name))) {
+ case 'start':
+ case 'start_date':
+ return [$this, 'getStartDate'];
+ case 'end':
+ case 'end_date':
+ return [$this, 'getEndDate'];
+ case 'interval':
+ case 'date_interval':
+ return [$this, 'getDateInterval'];
+ case 'recurrences':
+ return [$this, 'getRecurrences'];
+ case 'include_start_date':
+ return [$this, 'isStartIncluded'];
+ case 'include_end_date':
+ return [$this, 'isEndIncluded'];
+ case 'current':
+ return [$this, 'current'];
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Get a property allowing both `DatePeriod` snakeCase and camelCase names.
+ *
+ * @param string $name
+ *
+ * @return bool|CarbonInterface|CarbonInterval|int|null
+ */
+ public function get(string $name)
+ {
+ $getter = $this->getGetter($name);
+
+ if ($getter) {
+ return $getter();
+ }
+
+ throw new UnknownGetterException($name);
+ }
+
+ /**
+ * Get a property allowing both `DatePeriod` snakeCase and camelCase names.
+ *
+ * @param string $name
+ *
+ * @return bool|CarbonInterface|CarbonInterval|int|null
+ */
+ public function __get(string $name)
+ {
+ return $this->get($name);
+ }
+
+ /**
+ * Check if an attribute exists on the object
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function __isset(string $name): bool
+ {
+ return $this->getGetter($name) !== null;
+ }
+
+ /**
+ * @alias copy
+ *
+ * Get a copy of the instance.
+ *
+ * @return static
+ */
+ public function clone()
+ {
+ return clone $this;
+ }
+
+ /**
+ * Set the iteration item class.
+ *
+ * @param string $dateClass
+ *
+ * @return $this
+ */
+ public function setDateClass(string $dateClass)
+ {
+ if (!is_a($dateClass, CarbonInterface::class, true)) {
+ throw new NotACarbonClassException($dateClass);
+ }
+
+ $this->dateClass = $dateClass;
+
+ if (is_a($dateClass, Carbon::class, true)) {
+ $this->toggleOptions(static::IMMUTABLE, false);
+ } elseif (is_a($dateClass, CarbonImmutable::class, true)) {
+ $this->toggleOptions(static::IMMUTABLE, true);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns iteration item date class.
+ *
+ * @return string
+ */
+ public function getDateClass(): string
+ {
+ return $this->dateClass;
+ }
+
+ /**
+ * Change the period date interval.
+ *
+ * @param DateInterval|string $interval
+ *
+ * @throws InvalidIntervalException
+ *
+ * @return $this
+ */
+ public function setDateInterval($interval)
+ {
+ if (!$interval = CarbonInterval::make($interval)) {
+ throw new InvalidIntervalException('Invalid interval.');
+ }
+
+ if ($interval->spec() === 'PT0S' && !$interval->f && !$interval->getStep()) {
+ throw new InvalidIntervalException('Empty interval is not accepted.');
+ }
+
+ $this->dateInterval = $interval;
+
+ $this->isDefaultInterval = false;
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Invert the period date interval.
+ *
+ * @return $this
+ */
+ public function invertDateInterval()
+ {
+ $interval = $this->dateInterval->invert();
+
+ return $this->setDateInterval($interval);
+ }
+
+ /**
+ * Set start and end date.
+ *
+ * @param DateTime|DateTimeInterface|string $start
+ * @param DateTime|DateTimeInterface|string|null $end
+ *
+ * @return $this
+ */
+ public function setDates($start, $end)
+ {
+ $this->setStartDate($start);
+ $this->setEndDate($end);
+
+ return $this;
+ }
+
+ /**
+ * Change the period options.
+ *
+ * @param int|null $options
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function setOptions($options)
+ {
+ if (!\is_int($options) && $options !== null) {
+ throw new InvalidPeriodParameterException('Invalid options.');
+ }
+
+ $this->options = $options ?: 0;
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Get the period options.
+ *
+ * @return int
+ */
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * Toggle given options on or off.
+ *
+ * @param int $options
+ * @param bool|null $state
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function toggleOptions($options, $state = null)
+ {
+ if ($state === null) {
+ $state = ($this->options & $options) !== $options;
+ }
+
+ return $this->setOptions(
+ $state ?
+ $this->options | $options :
+ $this->options & ~$options
+ );
+ }
+
+ /**
+ * Toggle EXCLUDE_START_DATE option.
+ *
+ * @param bool $state
+ *
+ * @return $this
+ */
+ public function excludeStartDate($state = true)
+ {
+ return $this->toggleOptions(static::EXCLUDE_START_DATE, $state);
+ }
+
+ /**
+ * Toggle EXCLUDE_END_DATE option.
+ *
+ * @param bool $state
+ *
+ * @return $this
+ */
+ public function excludeEndDate($state = true)
+ {
+ return $this->toggleOptions(static::EXCLUDE_END_DATE, $state);
+ }
+
+ /**
+ * Get the underlying date interval.
+ *
+ * @return CarbonInterval
+ */
+ public function getDateInterval()
+ {
+ return $this->dateInterval->copy();
+ }
+
+ /**
+ * Get start date of the period.
+ *
+ * @param string|null $rounding Optional rounding 'floor', 'ceil', 'round' using the period interval.
+ *
+ * @return CarbonInterface
+ */
+ public function getStartDate(string $rounding = null)
+ {
+ $date = $this->startDate->avoidMutation();
+
+ return $rounding ? $date->round($this->getDateInterval(), $rounding) : $date;
+ }
+
+ /**
+ * Get end date of the period.
+ *
+ * @param string|null $rounding Optional rounding 'floor', 'ceil', 'round' using the period interval.
+ *
+ * @return CarbonInterface|null
+ */
+ public function getEndDate(string $rounding = null)
+ {
+ if (!$this->endDate) {
+ return null;
+ }
+
+ $date = $this->endDate->avoidMutation();
+
+ return $rounding ? $date->round($this->getDateInterval(), $rounding) : $date;
+ }
+
+ /**
+ * Get number of recurrences.
+ *
+ * @return int|float|null
+ */
+ public function getRecurrences()
+ {
+ return $this->recurrences;
+ }
+
+ /**
+ * Returns true if the start date should be excluded.
+ *
+ * @return bool
+ */
+ public function isStartExcluded()
+ {
+ return ($this->options & static::EXCLUDE_START_DATE) !== 0;
+ }
+
+ /**
+ * Returns true if the end date should be excluded.
+ *
+ * @return bool
+ */
+ public function isEndExcluded()
+ {
+ return ($this->options & static::EXCLUDE_END_DATE) !== 0;
+ }
+
+ /**
+ * Returns true if the start date should be included.
+ *
+ * @return bool
+ */
+ public function isStartIncluded()
+ {
+ return !$this->isStartExcluded();
+ }
+
+ /**
+ * Returns true if the end date should be included.
+ *
+ * @return bool
+ */
+ public function isEndIncluded()
+ {
+ return !$this->isEndExcluded();
+ }
+
+ /**
+ * Return the start if it's included by option, else return the start + 1 period interval.
+ *
+ * @return CarbonInterface
+ */
+ public function getIncludedStartDate()
+ {
+ $start = $this->getStartDate();
+
+ if ($this->isStartExcluded()) {
+ return $start->add($this->getDateInterval());
+ }
+
+ return $start;
+ }
+
+ /**
+ * Return the end if it's included by option, else return the end - 1 period interval.
+ * Warning: if the period has no fixed end, this method will iterate the period to calculate it.
+ *
+ * @return CarbonInterface
+ */
+ public function getIncludedEndDate()
+ {
+ $end = $this->getEndDate();
+
+ if (!$end) {
+ return $this->calculateEnd();
+ }
+
+ if ($this->isEndExcluded()) {
+ return $end->sub($this->getDateInterval());
+ }
+
+ return $end;
+ }
+
+ /**
+ * Add a filter to the stack.
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ *
+ * @param callable $callback
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function addFilter($callback, $name = null)
+ {
+ $tuple = $this->createFilterTuple(\func_get_args());
+
+ $this->filters[] = $tuple;
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Prepend a filter to the stack.
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ *
+ * @param callable $callback
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function prependFilter($callback, $name = null)
+ {
+ $tuple = $this->createFilterTuple(\func_get_args());
+
+ array_unshift($this->filters, $tuple);
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Remove a filter by instance or name.
+ *
+ * @param callable|string $filter
+ *
+ * @return $this
+ */
+ public function removeFilter($filter)
+ {
+ $key = \is_callable($filter) ? 0 : 1;
+
+ $this->filters = array_values(array_filter(
+ $this->filters,
+ function ($tuple) use ($key, $filter) {
+ return $tuple[$key] !== $filter;
+ }
+ ));
+
+ $this->updateInternalState();
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Return whether given instance or name is in the filter stack.
+ *
+ * @param callable|string $filter
+ *
+ * @return bool
+ */
+ public function hasFilter($filter)
+ {
+ $key = \is_callable($filter) ? 0 : 1;
+
+ foreach ($this->filters as $tuple) {
+ if ($tuple[$key] === $filter) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get filters stack.
+ *
+ * @return array
+ */
+ public function getFilters()
+ {
+ return $this->filters;
+ }
+
+ /**
+ * Set filters stack.
+ *
+ * @param array $filters
+ *
+ * @return $this
+ */
+ public function setFilters(array $filters)
+ {
+ $this->filters = $filters;
+
+ $this->updateInternalState();
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Reset filters stack.
+ *
+ * @return $this
+ */
+ public function resetFilters()
+ {
+ $this->filters = [];
+
+ if ($this->endDate !== null) {
+ $this->filters[] = [static::END_DATE_FILTER, null];
+ }
+
+ if ($this->recurrences !== null) {
+ $this->filters[] = [static::RECURRENCES_FILTER, null];
+ }
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Add a recurrences filter (set maximum number of recurrences).
+ *
+ * @param int|float|null $recurrences
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function setRecurrences($recurrences)
+ {
+ if (!is_numeric($recurrences) && $recurrences !== null || $recurrences < 0) {
+ throw new InvalidPeriodParameterException('Invalid number of recurrences.');
+ }
+
+ if ($recurrences === null) {
+ return $this->removeFilter(static::RECURRENCES_FILTER);
+ }
+
+ $this->recurrences = $recurrences === INF ? INF : (int) $recurrences;
+
+ if (!$this->hasFilter(static::RECURRENCES_FILTER)) {
+ return $this->addFilter(static::RECURRENCES_FILTER);
+ }
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Change the period start date.
+ *
+ * @param DateTime|DateTimeInterface|string $date
+ * @param bool|null $inclusive
+ *
+ * @throws InvalidPeriodDateException
+ *
+ * @return $this
+ */
+ public function setStartDate($date, $inclusive = null)
+ {
+ if (!$date = ([$this->dateClass, 'make'])($date)) {
+ throw new InvalidPeriodDateException('Invalid start date.');
+ }
+
+ $this->startDate = $date;
+
+ if ($inclusive !== null) {
+ $this->toggleOptions(static::EXCLUDE_START_DATE, !$inclusive);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Change the period end date.
+ *
+ * @param DateTime|DateTimeInterface|string|null $date
+ * @param bool|null $inclusive
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function setEndDate($date, $inclusive = null)
+ {
+ if ($date !== null && !$date = ([$this->dateClass, 'make'])($date)) {
+ throw new InvalidPeriodDateException('Invalid end date.');
+ }
+
+ if (!$date) {
+ return $this->removeFilter(static::END_DATE_FILTER);
+ }
+
+ $this->endDate = $date;
+
+ if ($inclusive !== null) {
+ $this->toggleOptions(static::EXCLUDE_END_DATE, !$inclusive);
+ }
+
+ if (!$this->hasFilter(static::END_DATE_FILTER)) {
+ return $this->addFilter(static::END_DATE_FILTER);
+ }
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Check if the current position is valid.
+ *
+ * @return bool
+ */
+ public function valid()
+ {
+ return $this->validateCurrentDate() === true;
+ }
+
+ /**
+ * Return the current key.
+ *
+ * @return int|null
+ */
+ public function key()
+ {
+ return $this->valid()
+ ? $this->key
+ : null;
+ }
+
+ /**
+ * Return the current date.
+ *
+ * @return CarbonInterface|null
+ */
+ public function current()
+ {
+ return $this->valid()
+ ? $this->prepareForReturn($this->current)
+ : null;
+ }
+
+ /**
+ * Move forward to the next date.
+ *
+ * @throws RuntimeException
+ *
+ * @return void
+ */
+ public function next()
+ {
+ if ($this->current === null) {
+ $this->rewind();
+ }
+
+ if ($this->validationResult !== static::END_ITERATION) {
+ $this->key++;
+
+ $this->incrementCurrentDateUntilValid();
+ }
+ }
+
+ /**
+ * Rewind to the start date.
+ *
+ * Iterating over a date in the UTC timezone avoids bug during backward DST change.
+ *
+ * @see https://bugs.php.net/bug.php?id=72255
+ * @see https://bugs.php.net/bug.php?id=74274
+ * @see https://wiki.php.net/rfc/datetime_and_daylight_saving_time
+ *
+ * @throws RuntimeException
+ *
+ * @return void
+ */
+ public function rewind()
+ {
+ $this->key = 0;
+ $this->current = ([$this->dateClass, 'make'])($this->startDate);
+ $settings = $this->getSettings();
+
+ if ($this->hasLocalTranslator()) {
+ $settings['locale'] = $this->getTranslatorLocale();
+ }
+
+ $this->current->settings($settings);
+ $this->timezone = static::intervalHasTime($this->dateInterval) ? $this->current->getTimezone() : null;
+
+ if ($this->timezone) {
+ $this->current = $this->current->utc();
+ }
+
+ $this->validationResult = null;
+
+ if ($this->isStartExcluded() || $this->validateCurrentDate() === false) {
+ $this->incrementCurrentDateUntilValid();
+ }
+ }
+
+ /**
+ * Skip iterations and returns iteration state (false if ended, true if still valid).
+ *
+ * @param int $count steps number to skip (1 by default)
+ *
+ * @return bool
+ */
+ public function skip($count = 1)
+ {
+ for ($i = $count; $this->valid() && $i > 0; $i--) {
+ $this->next();
+ }
+
+ return $this->valid();
+ }
+
+ /**
+ * Format the date period as ISO 8601.
+ *
+ * @return string
+ */
+ public function toIso8601String()
+ {
+ $parts = [];
+
+ if ($this->recurrences !== null) {
+ $parts[] = 'R'.$this->recurrences;
+ }
+
+ $parts[] = $this->startDate->toIso8601String();
+
+ $parts[] = $this->dateInterval->spec();
+
+ if ($this->endDate !== null) {
+ $parts[] = $this->endDate->toIso8601String();
+ }
+
+ return implode('/', $parts);
+ }
+
+ /**
+ * Convert the date period into a string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ $translator = ([$this->dateClass, 'getTranslator'])();
+
+ $parts = [];
+
+ $format = !$this->startDate->isStartOfDay() || $this->endDate && !$this->endDate->isStartOfDay()
+ ? 'Y-m-d H:i:s'
+ : 'Y-m-d';
+
+ if ($this->recurrences !== null) {
+ $parts[] = $this->translate('period_recurrences', [], $this->recurrences, $translator);
+ }
+
+ $parts[] = $this->translate('period_interval', [':interval' => $this->dateInterval->forHumans([
+ 'join' => true,
+ ])], null, $translator);
+
+ $parts[] = $this->translate('period_start_date', [':date' => $this->startDate->rawFormat($format)], null, $translator);
+
+ if ($this->endDate !== null) {
+ $parts[] = $this->translate('period_end_date', [':date' => $this->endDate->rawFormat($format)], null, $translator);
+ }
+
+ $result = implode(' ', $parts);
+
+ return mb_strtoupper(mb_substr($result, 0, 1)).mb_substr($result, 1);
+ }
+
+ /**
+ * Format the date period as ISO 8601.
+ *
+ * @return string
+ */
+ public function spec()
+ {
+ return $this->toIso8601String();
+ }
+
+ /**
+ * Cast the current instance into the given class.
+ *
+ * @param string $className The $className::instance() method will be called to cast the current object.
+ *
+ * @return DatePeriod
+ */
+ public function cast(string $className)
+ {
+ if (!method_exists($className, 'instance')) {
+ if (is_a($className, DatePeriod::class, true)) {
+ return new $className(
+ $this->getStartDate(),
+ $this->getDateInterval(),
+ $this->getEndDate() ? $this->getIncludedEndDate() : $this->getRecurrences(),
+ $this->isStartExcluded() ? DatePeriod::EXCLUDE_START_DATE : 0
+ );
+ }
+
+ throw new InvalidCastException("$className has not the instance() method needed to cast the date.");
+ }
+
+ return $className::instance($this);
+ }
+
+ /**
+ * Return native DatePeriod PHP object matching the current instance.
+ *
+ * @example
+ * ```
+ * var_dump(CarbonPeriod::create('2021-01-05', '2021-02-15')->toDatePeriod());
+ * ```
+ *
+ * @return DatePeriod
+ */
+ public function toDatePeriod()
+ {
+ return $this->cast(DatePeriod::class);
+ }
+
+ /**
+ * Convert the date period into an array without changing current iteration state.
+ *
+ * @return CarbonInterface[]
+ */
+ public function toArray()
+ {
+ $state = [
+ $this->key,
+ $this->current ? $this->current->avoidMutation() : null,
+ $this->validationResult,
+ ];
+
+ $result = iterator_to_array($this);
+
+ [$this->key, $this->current, $this->validationResult] = $state;
+
+ return $result;
+ }
+
+ /**
+ * Count dates in the date period.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return \count($this->toArray());
+ }
+
+ /**
+ * Return the first date in the date period.
+ *
+ * @return CarbonInterface|null
+ */
+ public function first()
+ {
+ return ($this->toArray() ?: [])[0] ?? null;
+ }
+
+ /**
+ * Return the last date in the date period.
+ *
+ * @return CarbonInterface|null
+ */
+ public function last()
+ {
+ $array = $this->toArray();
+
+ return $array ? $array[\count($array) - 1] : null;
+ }
+
+ /**
+ * Convert the date period into a string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ /**
+ * Add aliases for setters.
+ *
+ * CarbonPeriod::days(3)->hours(5)->invert()
+ * ->sinceNow()->until('2010-01-10')
+ * ->filter(...)
+ * ->count()
+ *
+ * Note: We use magic method to let static and instance aliases with the same names.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ if (static::hasMacro($method)) {
+ return static::bindMacroContext($this, function () use (&$method, &$parameters) {
+ return $this->callMacro($method, $parameters);
+ });
+ }
+
+ $roundedValue = $this->callRoundMethod($method, $parameters);
+
+ if ($roundedValue !== null) {
+ return $roundedValue;
+ }
+
+ $first = \count($parameters) >= 1 ? $parameters[0] : null;
+ $second = \count($parameters) >= 2 ? $parameters[1] : null;
+
+ switch ($method) {
+ case 'start':
+ case 'since':
+ return $this->setStartDate($first, $second);
+
+ case 'sinceNow':
+ return $this->setStartDate(new Carbon, $first);
+
+ case 'end':
+ case 'until':
+ return $this->setEndDate($first, $second);
+
+ case 'untilNow':
+ return $this->setEndDate(new Carbon, $first);
+
+ case 'dates':
+ case 'between':
+ return $this->setDates($first, $second);
+
+ case 'recurrences':
+ case 'times':
+ return $this->setRecurrences($first);
+
+ case 'options':
+ return $this->setOptions($first);
+
+ case 'toggle':
+ return $this->toggleOptions($first, $second);
+
+ case 'filter':
+ case 'push':
+ return $this->addFilter($first, $second);
+
+ case 'prepend':
+ return $this->prependFilter($first, $second);
+
+ case 'filters':
+ return $this->setFilters($first ?: []);
+
+ case 'interval':
+ case 'each':
+ case 'every':
+ case 'step':
+ case 'stepBy':
+ return $this->setDateInterval($first);
+
+ case 'invert':
+ return $this->invertDateInterval();
+
+ case 'years':
+ case 'year':
+ case 'months':
+ case 'month':
+ case 'weeks':
+ case 'week':
+ case 'days':
+ case 'dayz':
+ case 'day':
+ case 'hours':
+ case 'hour':
+ case 'minutes':
+ case 'minute':
+ case 'seconds':
+ case 'second':
+ return $this->setDateInterval((
+ // Override default P1D when instantiating via fluent setters.
+ [$this->isDefaultInterval ? new CarbonInterval('PT0S') : $this->dateInterval, $method]
+ )(
+ \count($parameters) === 0 ? 1 : $first
+ ));
+ }
+
+ if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
+ throw new UnknownMethodException($method);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the instance's timezone from a string or object and add/subtract the offset difference.
+ *
+ * @param \DateTimeZone|string $timezone
+ *
+ * @return static
+ */
+ public function shiftTimezone($timezone)
+ {
+ $this->tzName = $timezone;
+ $this->timezone = $timezone;
+
+ return $this;
+ }
+
+ /**
+ * Returns the end is set, else calculated from start an recurrences.
+ *
+ * @param string|null $rounding Optional rounding 'floor', 'ceil', 'round' using the period interval.
+ *
+ * @return CarbonInterface
+ */
+ public function calculateEnd(string $rounding = null)
+ {
+ if ($end = $this->getEndDate($rounding)) {
+ return $end;
+ }
+
+ if ($this->dateInterval->isEmpty()) {
+ return $this->getStartDate($rounding);
+ }
+
+ $date = $this->getEndFromRecurrences() ?? $this->iterateUntilEnd();
+
+ if ($date && $rounding) {
+ $date = $date->avoidMutation()->round($this->getDateInterval(), $rounding);
+ }
+
+ return $date;
+ }
+
+ /**
+ * @return CarbonInterface|null
+ */
+ private function getEndFromRecurrences()
+ {
+ if ($this->recurrences === null) {
+ throw new UnreachableException(
+ "Could not calculate period end without either explicit end or recurrences.\n".
+ "If you're looking for a forever-period, use ->setRecurrences(INF)."
+ );
+ }
+
+ if ($this->recurrences === INF) {
+ $start = $this->getStartDate();
+
+ return $start < $start->avoidMutation()->add($this->getDateInterval())
+ ? CarbonImmutable::endOfTime()
+ : CarbonImmutable::startOfTime();
+ }
+
+ if ($this->filters === [[static::RECURRENCES_FILTER, null]]) {
+ return $this->getStartDate()->avoidMutation()->add(
+ $this->getDateInterval()->times(
+ $this->recurrences - ($this->isStartExcluded() ? 0 : 1)
+ )
+ );
+ }
+
+ return null;
+ }
+
+ /**
+ * @return CarbonInterface|null
+ */
+ private function iterateUntilEnd()
+ {
+ $attempts = 0;
+ $date = null;
+
+ foreach ($this as $date) {
+ if (++$attempts > static::END_MAX_ATTEMPTS) {
+ throw new UnreachableException(
+ 'Could not calculate period end after iterating '.static::END_MAX_ATTEMPTS.' times.'
+ );
+ }
+ }
+
+ return $date;
+ }
+
+ /**
+ * Returns true if the current period overlaps the given one (if 1 parameter passed)
+ * or the period between 2 dates (if 2 parameters passed).
+ *
+ * @param CarbonPeriod|\DateTimeInterface|Carbon|CarbonImmutable|string $rangeOrRangeStart
+ * @param \DateTimeInterface|Carbon|CarbonImmutable|string|null $rangeEnd
+ *
+ * @return bool
+ */
+ public function overlaps($rangeOrRangeStart, $rangeEnd = null)
+ {
+ $range = $rangeEnd ? static::create($rangeOrRangeStart, $rangeEnd) : $rangeOrRangeStart;
+
+ if (!($range instanceof self)) {
+ $range = static::create($range);
+ }
+
+ [$start, $end] = $this->orderCouple($this->getStartDate(), $this->calculateEnd());
+ [$rangeStart, $rangeEnd] = $this->orderCouple($range->getStartDate(), $range->calculateEnd());
+
+ return $end > $rangeStart && $rangeEnd > $start;
+ }
+
+ /**
+ * Execute a given function on each date of the period.
+ *
+ * @example
+ * ```
+ * Carbon::create('2020-11-29')->daysUntil('2020-12-24')->forEach(function (Carbon $date) {
+ * echo $date->diffInDays('2020-12-25')." days before Christmas!\n";
+ * });
+ * ```
+ *
+ * @param callable $callback
+ */
+ public function forEach(callable $callback)
+ {
+ foreach ($this as $date) {
+ $callback($date);
+ }
+ }
+
+ /**
+ * Execute a given function on each date of the period and yield the result of this function.
+ *
+ * @example
+ * ```
+ * $period = Carbon::create('2020-11-29')->daysUntil('2020-12-24');
+ * echo implode("\n", iterator_to_array($period->map(function (Carbon $date) {
+ * return $date->diffInDays('2020-12-25').' days before Christmas!';
+ * })));
+ * ```
+ *
+ * @param callable $callback
+ *
+ * @return \Generator
+ */
+ public function map(callable $callback)
+ {
+ foreach ($this as $date) {
+ yield $callback($date);
+ }
+ }
+
+ /**
+ * Determines if the instance is equal to another.
+ * Warning: if options differ, instances wil never be equal.
+ *
+ * @param mixed $period
+ *
+ * @see equalTo()
+ *
+ * @return bool
+ */
+ public function eq($period): bool
+ {
+ return $this->equalTo($period);
+ }
+
+ /**
+ * Determines if the instance is equal to another.
+ * Warning: if options differ, instances wil never be equal.
+ *
+ * @param mixed $period
+ *
+ * @return bool
+ */
+ public function equalTo($period): bool
+ {
+ if (!($period instanceof self)) {
+ $period = self::make($period);
+ }
+
+ $end = $this->getEndDate();
+
+ return $period !== null
+ && $this->getDateInterval()->eq($period->getDateInterval())
+ && $this->getStartDate()->eq($period->getStartDate())
+ && ($end ? $end->eq($period->getEndDate()) : $this->getRecurrences() === $period->getRecurrences())
+ && ($this->getOptions() & (~static::IMMUTABLE)) === ($period->getOptions() & (~static::IMMUTABLE));
+ }
+
+ /**
+ * Determines if the instance is not equal to another.
+ * Warning: if options differ, instances wil never be equal.
+ *
+ * @param mixed $period
+ *
+ * @see notEqualTo()
+ *
+ * @return bool
+ */
+ public function ne($period): bool
+ {
+ return $this->notEqualTo($period);
+ }
+
+ /**
+ * Determines if the instance is not equal to another.
+ * Warning: if options differ, instances wil never be equal.
+ *
+ * @param mixed $period
+ *
+ * @return bool
+ */
+ public function notEqualTo($period): bool
+ {
+ return !$this->eq($period);
+ }
+
+ /**
+ * Determines if the start date is before an other given date.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @param mixed $date
+ *
+ * @return bool
+ */
+ public function startsBefore($date = null): bool
+ {
+ return $this->getStartDate()->lessThan($this->resolveCarbon($date));
+ }
+
+ /**
+ * Determines if the start date is before or the same as a given date.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @param mixed $date
+ *
+ * @return bool
+ */
+ public function startsBeforeOrAt($date = null): bool
+ {
+ return $this->getStartDate()->lessThanOrEqualTo($this->resolveCarbon($date));
+ }
+
+ /**
+ * Determines if the start date is after an other given date.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @param mixed $date
+ *
+ * @return bool
+ */
+ public function startsAfter($date = null): bool
+ {
+ return $this->getStartDate()->greaterThan($this->resolveCarbon($date));
+ }
+
+ /**
+ * Determines if the start date is after or the same as a given date.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @param mixed $date
+ *
+ * @return bool
+ */
+ public function startsAfterOrAt($date = null): bool
+ {
+ return $this->getStartDate()->greaterThanOrEqualTo($this->resolveCarbon($date));
+ }
+
+ /**
+ * Determines if the start date is the same as a given date.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @param mixed $date
+ *
+ * @return bool
+ */
+ public function startsAt($date = null): bool
+ {
+ return $this->getStartDate()->equalTo($this->resolveCarbon($date));
+ }
+
+ /**
+ * Determines if the end date is before an other given date.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @param mixed $date
+ *
+ * @return bool
+ */
+ public function endsBefore($date = null): bool
+ {
+ return $this->calculateEnd()->lessThan($this->resolveCarbon($date));
+ }
+
+ /**
+ * Determines if the end date is before or the same as a given date.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @param mixed $date
+ *
+ * @return bool
+ */
+ public function endsBeforeOrAt($date = null): bool
+ {
+ return $this->calculateEnd()->lessThanOrEqualTo($this->resolveCarbon($date));
+ }
+
+ /**
+ * Determines if the end date is after an other given date.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @param mixed $date
+ *
+ * @return bool
+ */
+ public function endsAfter($date = null): bool
+ {
+ return $this->calculateEnd()->greaterThan($this->resolveCarbon($date));
+ }
+
+ /**
+ * Determines if the end date is after or the same as a given date.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @param mixed $date
+ *
+ * @return bool
+ */
+ public function endsAfterOrAt($date = null): bool
+ {
+ return $this->calculateEnd()->greaterThanOrEqualTo($this->resolveCarbon($date));
+ }
+
+ /**
+ * Determines if the end date is the same as a given date.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @param mixed $date
+ *
+ * @return bool
+ */
+ public function endsAt($date = null): bool
+ {
+ return $this->calculateEnd()->equalTo($this->resolveCarbon($date));
+ }
+
+ /**
+ * Return true if start date is now or later.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @return bool
+ */
+ public function isStarted(): bool
+ {
+ return $this->startsBeforeOrAt();
+ }
+
+ /**
+ * Return true if end date is now or later.
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @return bool
+ */
+ public function isEnded(): bool
+ {
+ return $this->endsBeforeOrAt();
+ }
+
+ /**
+ * Return true if now is between start date (included) and end date (excluded).
+ * (Rather start/end are included by options is ignored.)
+ *
+ * @return bool
+ */
+ public function isInProgress(): bool
+ {
+ return $this->isStarted() && !$this->isEnded();
+ }
+
+ /**
+ * Round the current instance at the given unit with given precision if specified and the given function.
+ *
+ * @param string $unit
+ * @param float|int|string|\DateInterval|null $precision
+ * @param string $function
+ *
+ * @return $this
+ */
+ public function roundUnit($unit, $precision = 1, $function = 'round')
+ {
+ $this->setStartDate($this->getStartDate()->roundUnit($unit, $precision, $function));
+
+ if ($this->endDate) {
+ $this->setEndDate($this->getEndDate()->roundUnit($unit, $precision, $function));
+ }
+
+ $this->setDateInterval($this->getDateInterval()->roundUnit($unit, $precision, $function));
+
+ return $this;
+ }
+
+ /**
+ * Truncate the current instance at the given unit with given precision if specified.
+ *
+ * @param string $unit
+ * @param float|int|string|\DateInterval|null $precision
+ *
+ * @return $this
+ */
+ public function floorUnit($unit, $precision = 1)
+ {
+ return $this->roundUnit($unit, $precision, 'floor');
+ }
+
+ /**
+ * Ceil the current instance at the given unit with given precision if specified.
+ *
+ * @param string $unit
+ * @param float|int|string|\DateInterval|null $precision
+ *
+ * @return $this
+ */
+ public function ceilUnit($unit, $precision = 1)
+ {
+ return $this->roundUnit($unit, $precision, 'ceil');
+ }
+
+ /**
+ * Round the current instance second with given precision if specified (else period interval is used).
+ *
+ * @param float|int|string|\DateInterval|null $precision
+ * @param string $function
+ *
+ * @return $this
+ */
+ public function round($precision = null, $function = 'round')
+ {
+ return $this->roundWith($precision ?? (string) $this->getDateInterval(), $function);
+ }
+
+ /**
+ * Round the current instance second with given precision if specified (else period interval is used).
+ *
+ * @param float|int|string|\DateInterval|null $precision
+ *
+ * @return $this
+ */
+ public function floor($precision = null)
+ {
+ return $this->round($precision, 'floor');
+ }
+
+ /**
+ * Ceil the current instance second with given precision if specified (else period interval is used).
+ *
+ * @param float|int|string|\DateInterval|null $precision
+ *
+ * @return $this
+ */
+ public function ceil($precision = null)
+ {
+ return $this->round($precision, 'ceil');
+ }
+
+ /**
+ * Specify data which should be serialized to JSON.
+ *
+ * @link https://php.net/manual/en/jsonserializable.jsonserialize.php
+ *
+ * @return CarbonInterface[]
+ */
+ #[ReturnTypeWillChange]
+ public function jsonSerialize()
+ {
+ return $this->toArray();
+ }
+
+ /**
+ * Return true if the given date is between start and end.
+ *
+ * @param \Carbon\Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|\DateTimeInterface|string|null $date
+ *
+ * @return bool
+ */
+ public function contains($date = null): bool
+ {
+ $startMethod = 'startsBefore'.($this->isStartIncluded() ? 'OrAt' : '');
+ $endMethod = 'endsAfter'.($this->isEndIncluded() ? 'OrAt' : '');
+
+ return $this->$startMethod($date) && $this->$endMethod($date);
+ }
+
+ /**
+ * Return true if the current period follows a given other period (with no overlap).
+ * For instance, [2019-08-01 -> 2019-08-12] follows [2019-07-29 -> 2019-07-31]
+ * Note than in this example, follows() would be false if 2019-08-01 or 2019-07-31 was excluded by options.
+ *
+ * @param \Carbon\CarbonPeriod|\DatePeriod|string $period
+ *
+ * @return bool
+ */
+ public function follows($period, ...$arguments): bool
+ {
+ $period = $this->resolveCarbonPeriod($period, ...$arguments);
+
+ return $this->getIncludedStartDate()->equalTo($period->getIncludedEndDate()->add($period->getDateInterval()));
+ }
+
+ /**
+ * Return true if the given other period follows the current one (with no overlap).
+ * For instance, [2019-07-29 -> 2019-07-31] is followed by [2019-08-01 -> 2019-08-12]
+ * Note than in this example, isFollowedBy() would be false if 2019-08-01 or 2019-07-31 was excluded by options.
+ *
+ * @param \Carbon\CarbonPeriod|\DatePeriod|string $period
+ *
+ * @return bool
+ */
+ public function isFollowedBy($period, ...$arguments): bool
+ {
+ $period = $this->resolveCarbonPeriod($period, ...$arguments);
+
+ return $period->follows($this);
+ }
+
+ /**
+ * Return true if the given period either follows or is followed by the current one.
+ *
+ * @see follows()
+ * @see isFollowedBy()
+ *
+ * @param \Carbon\CarbonPeriod|\DatePeriod|string $period
+ *
+ * @return bool
+ */
+ public function isConsecutiveWith($period, ...$arguments): bool
+ {
+ return $this->follows($period, ...$arguments) || $this->isFollowedBy($period, ...$arguments);
+ }
+
+ /**
+ * Update properties after removing built-in filters.
+ *
+ * @return void
+ */
+ protected function updateInternalState()
+ {
+ if (!$this->hasFilter(static::END_DATE_FILTER)) {
+ $this->endDate = null;
+ }
+
+ if (!$this->hasFilter(static::RECURRENCES_FILTER)) {
+ $this->recurrences = null;
+ }
+ }
+
+ /**
+ * Create a filter tuple from raw parameters.
+ *
+ * Will create an automatic filter callback for one of Carbon's is* methods.
+ *
+ * @param array $parameters
+ *
+ * @return array
+ */
+ protected function createFilterTuple(array $parameters)
+ {
+ $method = array_shift($parameters);
+
+ if (!$this->isCarbonPredicateMethod($method)) {
+ return [$method, array_shift($parameters)];
+ }
+
+ return [function ($date) use ($method, $parameters) {
+ return ([$date, $method])(...$parameters);
+ }, $method];
+ }
+
+ /**
+ * Return whether given callable is a string pointing to one of Carbon's is* methods
+ * and should be automatically converted to a filter callback.
+ *
+ * @param callable $callable
+ *
+ * @return bool
+ */
+ protected function isCarbonPredicateMethod($callable)
+ {
+ return \is_string($callable) && str_starts_with($callable, 'is') &&
+ (method_exists($this->dateClass, $callable) || ([$this->dateClass, 'hasMacro'])($callable));
+ }
+
+ /**
+ * Recurrences filter callback (limits number of recurrences).
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ *
+ * @param \Carbon\Carbon $current
+ * @param int $key
+ *
+ * @return bool|string
+ */
+ protected function filterRecurrences($current, $key)
+ {
+ if ($key < $this->recurrences) {
+ return true;
+ }
+
+ return static::END_ITERATION;
+ }
+
+ /**
+ * End date filter callback.
+ *
+ * @param \Carbon\Carbon $current
+ *
+ * @return bool|string
+ */
+ protected function filterEndDate($current)
+ {
+ if (!$this->isEndExcluded() && $current == $this->endDate) {
+ return true;
+ }
+
+ if ($this->dateInterval->invert ? $current > $this->endDate : $current < $this->endDate) {
+ return true;
+ }
+
+ return static::END_ITERATION;
+ }
+
+ /**
+ * End iteration filter callback.
+ *
+ * @return string
+ */
+ protected function endIteration()
+ {
+ return static::END_ITERATION;
+ }
+
+ /**
+ * Handle change of the parameters.
+ */
+ protected function handleChangedParameters()
+ {
+ if (($this->getOptions() & static::IMMUTABLE) && $this->dateClass === Carbon::class) {
+ $this->setDateClass(CarbonImmutable::class);
+ } elseif (!($this->getOptions() & static::IMMUTABLE) && $this->dateClass === CarbonImmutable::class) {
+ $this->setDateClass(Carbon::class);
+ }
+
+ $this->validationResult = null;
+ }
+
+ /**
+ * Validate current date and stop iteration when necessary.
+ *
+ * Returns true when current date is valid, false if it is not, or static::END_ITERATION
+ * when iteration should be stopped.
+ *
+ * @return bool|string
+ */
+ protected function validateCurrentDate()
+ {
+ if ($this->current === null) {
+ $this->rewind();
+ }
+
+ // Check after the first rewind to avoid repeating the initial validation.
+ if ($this->validationResult !== null) {
+ return $this->validationResult;
+ }
+
+ return $this->validationResult = $this->checkFilters();
+ }
+
+ /**
+ * Check whether current value and key pass all the filters.
+ *
+ * @return bool|string
+ */
+ protected function checkFilters()
+ {
+ $current = $this->prepareForReturn($this->current);
+
+ foreach ($this->filters as $tuple) {
+ $result = \call_user_func(
+ $tuple[0],
+ $current->avoidMutation(),
+ $this->key,
+ $this
+ );
+
+ if ($result === static::END_ITERATION) {
+ return static::END_ITERATION;
+ }
+
+ if (!$result) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Prepare given date to be returned to the external logic.
+ *
+ * @param CarbonInterface $date
+ *
+ * @return CarbonInterface
+ */
+ protected function prepareForReturn(CarbonInterface $date)
+ {
+ $date = ([$this->dateClass, 'make'])($date);
+
+ if ($this->timezone) {
+ $date = $date->setTimezone($this->timezone);
+ }
+
+ return $date;
+ }
+
+ /**
+ * Keep incrementing the current date until a valid date is found or the iteration is ended.
+ *
+ * @throws RuntimeException
+ *
+ * @return void
+ */
+ protected function incrementCurrentDateUntilValid()
+ {
+ $attempts = 0;
+
+ do {
+ $this->current = $this->current->add($this->dateInterval);
+
+ $this->validationResult = null;
+
+ if (++$attempts > static::NEXT_MAX_ATTEMPTS) {
+ throw new UnreachableException('Could not find next valid date.');
+ }
+ } while ($this->validateCurrentDate() === false);
+ }
+
+ /**
+ * Call given macro.
+ *
+ * @param string $name
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ protected function callMacro($name, $parameters)
+ {
+ $macro = static::$macros[$name];
+
+ if ($macro instanceof Closure) {
+ $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class);
+
+ return ($boundMacro ?: $macro)(...$parameters);
+ }
+
+ return $macro(...$parameters);
+ }
+
+ /**
+ * Return the Carbon instance passed through, a now instance in the same timezone
+ * if null given or parse the input if string given.
+ *
+ * @param \Carbon\Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|\DateTimeInterface|string|null $date
+ *
+ * @return \Carbon\CarbonInterface
+ */
+ protected function resolveCarbon($date = null)
+ {
+ return $this->getStartDate()->nowWithSameTz()->carbonize($date);
+ }
+
+ /**
+ * Resolve passed arguments or DatePeriod to a CarbonPeriod object.
+ *
+ * @param mixed $period
+ * @param mixed ...$arguments
+ *
+ * @return static
+ */
+ protected function resolveCarbonPeriod($period, ...$arguments)
+ {
+ if ($period instanceof self) {
+ return $period;
+ }
+
+ return $period instanceof DatePeriod
+ ? static::instance($period)
+ : static::create($period, ...$arguments);
+ }
+
+ private function orderCouple($first, $second): array
+ {
+ return $first > $second ? [$second, $first] : [$first, $second];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php
new file mode 100644
index 0000000..2bd36c4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php
@@ -0,0 +1,306 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use Carbon\Exceptions\InvalidCastException;
+use Carbon\Exceptions\InvalidTimeZoneException;
+use DateTimeInterface;
+use DateTimeZone;
+
+class CarbonTimeZone extends DateTimeZone
+{
+ public function __construct($timezone = null)
+ {
+ parent::__construct(static::getDateTimeZoneNameFromMixed($timezone));
+ }
+
+ protected static function parseNumericTimezone($timezone)
+ {
+ if ($timezone <= -100 || $timezone >= 100) {
+ throw new InvalidTimeZoneException('Absolute timezone offset cannot be greater than 100.');
+ }
+
+ return ($timezone >= 0 ? '+' : '').$timezone.':00';
+ }
+
+ protected static function getDateTimeZoneNameFromMixed($timezone)
+ {
+ if ($timezone === null) {
+ return date_default_timezone_get();
+ }
+
+ if (\is_string($timezone)) {
+ $timezone = preg_replace('/^\s*([+-]\d+)(\d{2})\s*$/', '$1:$2', $timezone);
+ }
+
+ if (is_numeric($timezone)) {
+ return static::parseNumericTimezone($timezone);
+ }
+
+ return $timezone;
+ }
+
+ protected static function getDateTimeZoneFromName(&$name)
+ {
+ return @timezone_open($name = (string) static::getDateTimeZoneNameFromMixed($name));
+ }
+
+ /**
+ * Cast the current instance into the given class.
+ *
+ * @param string $className The $className::instance() method will be called to cast the current object.
+ *
+ * @return DateTimeZone
+ */
+ public function cast(string $className)
+ {
+ if (!method_exists($className, 'instance')) {
+ if (is_a($className, DateTimeZone::class, true)) {
+ return new $className($this->getName());
+ }
+
+ throw new InvalidCastException("$className has not the instance() method needed to cast the date.");
+ }
+
+ return $className::instance($this);
+ }
+
+ /**
+ * Create a CarbonTimeZone from mixed input.
+ *
+ * @param DateTimeZone|string|int|null $object original value to get CarbonTimeZone from it.
+ * @param DateTimeZone|string|int|null $objectDump dump of the object for error messages.
+ *
+ * @throws InvalidTimeZoneException
+ *
+ * @return false|static
+ */
+ public static function instance($object = null, $objectDump = null)
+ {
+ $tz = $object;
+
+ if ($tz instanceof static) {
+ return $tz;
+ }
+
+ if ($tz === null) {
+ return new static();
+ }
+
+ if (!$tz instanceof DateTimeZone) {
+ $tz = static::getDateTimeZoneFromName($object);
+ }
+
+ if ($tz === false) {
+ if (Carbon::isStrictModeEnabled()) {
+ throw new InvalidTimeZoneException('Unknown or bad timezone ('.($objectDump ?: $object).')');
+ }
+
+ return false;
+ }
+
+ return new static($tz->getName());
+ }
+
+ /**
+ * Returns abbreviated name of the current timezone according to DST setting.
+ *
+ * @param bool $dst
+ *
+ * @return string
+ */
+ public function getAbbreviatedName($dst = false)
+ {
+ $name = $this->getName();
+
+ foreach ($this->listAbbreviations() as $abbreviation => $zones) {
+ foreach ($zones as $zone) {
+ if ($zone['timezone_id'] === $name && $zone['dst'] == $dst) {
+ return $abbreviation;
+ }
+ }
+ }
+
+ return 'unknown';
+ }
+
+ /**
+ * @alias getAbbreviatedName
+ *
+ * Returns abbreviated name of the current timezone according to DST setting.
+ *
+ * @param bool $dst
+ *
+ * @return string
+ */
+ public function getAbbr($dst = false)
+ {
+ return $this->getAbbreviatedName($dst);
+ }
+
+ /**
+ * Get the offset as string "sHH:MM" (such as "+00:00" or "-12:30").
+ *
+ * @param DateTimeInterface|null $date
+ *
+ * @return string
+ */
+ public function toOffsetName(DateTimeInterface $date = null)
+ {
+ return static::getOffsetNameFromMinuteOffset(
+ $this->getOffset($date ?: Carbon::now($this)) / 60
+ );
+ }
+
+ /**
+ * Returns a new CarbonTimeZone object using the offset string instead of region string.
+ *
+ * @param DateTimeInterface|null $date
+ *
+ * @return CarbonTimeZone
+ */
+ public function toOffsetTimeZone(DateTimeInterface $date = null)
+ {
+ return new static($this->toOffsetName($date));
+ }
+
+ /**
+ * Returns the first region string (such as "America/Toronto") that matches the current timezone or
+ * false if no match is found.
+ *
+ * @see timezone_name_from_abbr native PHP function.
+ *
+ * @param DateTimeInterface|null $date
+ * @param int $isDst
+ *
+ * @return string|false
+ */
+ public function toRegionName(DateTimeInterface $date = null, $isDst = 1)
+ {
+ $name = $this->getName();
+ $firstChar = substr($name, 0, 1);
+
+ if ($firstChar !== '+' && $firstChar !== '-') {
+ return $name;
+ }
+
+ $date = $date ?: Carbon::now($this);
+
+ // Integer construction no longer supported since PHP 8
+ // @codeCoverageIgnoreStart
+ try {
+ $offset = @$this->getOffset($date) ?: 0;
+ } catch (\Throwable $e) {
+ $offset = 0;
+ }
+ // @codeCoverageIgnoreEnd
+
+ $name = @timezone_name_from_abbr('', $offset, $isDst);
+
+ if ($name) {
+ return $name;
+ }
+
+ foreach (timezone_identifiers_list() as $timezone) {
+ if (Carbon::instance($date)->tz($timezone)->getOffset() === $offset) {
+ return $timezone;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a new CarbonTimeZone object using the region string instead of offset string.
+ *
+ * @param DateTimeInterface|null $date
+ *
+ * @return CarbonTimeZone|false
+ */
+ public function toRegionTimeZone(DateTimeInterface $date = null)
+ {
+ $tz = $this->toRegionName($date);
+
+ if ($tz === false) {
+ if (Carbon::isStrictModeEnabled()) {
+ throw new InvalidTimeZoneException('Unknown timezone for offset '.$this->getOffset($date ?: Carbon::now($this)).' seconds.');
+ }
+
+ return false;
+ }
+
+ return new static($tz);
+ }
+
+ /**
+ * Cast to string (get timezone name).
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->getName();
+ }
+
+ /**
+ * Create a CarbonTimeZone from mixed input.
+ *
+ * @param DateTimeZone|string|int|null $object
+ *
+ * @return false|static
+ */
+ public static function create($object = null)
+ {
+ return static::instance($object);
+ }
+
+ /**
+ * Create a CarbonTimeZone from int/float hour offset.
+ *
+ * @param float $hourOffset number of hour of the timezone shift (can be decimal).
+ *
+ * @return false|static
+ */
+ public static function createFromHourOffset(float $hourOffset)
+ {
+ return static::createFromMinuteOffset($hourOffset * Carbon::MINUTES_PER_HOUR);
+ }
+
+ /**
+ * Create a CarbonTimeZone from int/float minute offset.
+ *
+ * @param float $minuteOffset number of total minutes of the timezone shift.
+ *
+ * @return false|static
+ */
+ public static function createFromMinuteOffset(float $minuteOffset)
+ {
+ return static::instance(static::getOffsetNameFromMinuteOffset($minuteOffset));
+ }
+
+ /**
+ * Convert a total minutes offset into a standardized timezone offset string.
+ *
+ * @param float $minutes number of total minutes of the timezone shift.
+ *
+ * @return string
+ */
+ public static function getOffsetNameFromMinuteOffset(float $minutes): string
+ {
+ $minutes = round($minutes);
+ $unsignedMinutes = abs($minutes);
+
+ return ($minutes < 0 ? '-' : '+').
+ str_pad((string) floor($unsignedMinutes / 60), 2, '0', STR_PAD_LEFT).
+ ':'.
+ str_pad((string) ($unsignedMinutes % 60), 2, '0', STR_PAD_LEFT);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Cli/Invoker.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Cli/Invoker.php
new file mode 100644
index 0000000..d53b1f4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Cli/Invoker.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Carbon\Cli;
+
+class Invoker
+{
+ public const CLI_CLASS_NAME = 'Carbon\\Cli';
+
+ protected function runWithCli(string $className, array $parameters): bool
+ {
+ $cli = new $className();
+
+ return $cli(...$parameters);
+ }
+
+ public function __invoke(...$parameters): bool
+ {
+ if (class_exists(self::CLI_CLASS_NAME)) {
+ return $this->runWithCli(self::CLI_CLASS_NAME, $parameters);
+ }
+
+ $function = (($parameters[1] ?? '') === 'install' ? ($parameters[2] ?? null) : null) ?: 'shell_exec';
+ $function('composer require carbon-cli/carbon-cli --no-interaction');
+
+ echo 'Installation succeeded.';
+
+ return true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonDoctrineType.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonDoctrineType.php
new file mode 100644
index 0000000..35c5558
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonDoctrineType.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * Thanks to https://github.com/flaushi for his suggestion:
+ * https://github.com/doctrine/dbal/issues/2873#issuecomment-534956358
+ */
+namespace Carbon\Doctrine;
+
+use Doctrine\DBAL\Platforms\AbstractPlatform;
+
+interface CarbonDoctrineType
+{
+ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform);
+
+ public function convertToPHPValue($value, AbstractPlatform $platform);
+
+ public function convertToDatabaseValue($value, AbstractPlatform $platform);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonImmutableType.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonImmutableType.php
new file mode 100644
index 0000000..3239743
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonImmutableType.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * Thanks to https://github.com/flaushi for his suggestion:
+ * https://github.com/doctrine/dbal/issues/2873#issuecomment-534956358
+ */
+namespace Carbon\Doctrine;
+
+use Doctrine\DBAL\Platforms\AbstractPlatform;
+
+class CarbonImmutableType extends DateTimeImmutableType implements CarbonDoctrineType
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'carbon_immutable';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function requiresSQLCommentHint(AbstractPlatform $platform)
+ {
+ return true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonType.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonType.php
new file mode 100644
index 0000000..e5f52c7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonType.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * Thanks to https://github.com/flaushi for his suggestion:
+ * https://github.com/doctrine/dbal/issues/2873#issuecomment-534956358
+ */
+namespace Carbon\Doctrine;
+
+use Doctrine\DBAL\Platforms\AbstractPlatform;
+
+class CarbonType extends DateTimeType implements CarbonDoctrineType
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'carbon';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function requiresSQLCommentHint(AbstractPlatform $platform)
+ {
+ return true;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonTypeConverter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonTypeConverter.php
new file mode 100644
index 0000000..fa0d5b0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonTypeConverter.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * Thanks to https://github.com/flaushi for his suggestion:
+ * https://github.com/doctrine/dbal/issues/2873#issuecomment-534956358
+ */
+namespace Carbon\Doctrine;
+
+use Carbon\Carbon;
+use Carbon\CarbonInterface;
+use DateTimeInterface;
+use Doctrine\DBAL\Platforms\AbstractPlatform;
+use Doctrine\DBAL\Types\ConversionException;
+use Exception;
+
+/**
+ * @template T of CarbonInterface
+ */
+trait CarbonTypeConverter
+{
+ /**
+ * @return class-string<T>
+ */
+ protected function getCarbonClassName(): string
+ {
+ return Carbon::class;
+ }
+
+ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
+ {
+ $precision = ($fieldDeclaration['precision'] ?: 10) === 10
+ ? DateTimeDefaultPrecision::get()
+ : $fieldDeclaration['precision'];
+ $type = parent::getSQLDeclaration($fieldDeclaration, $platform);
+
+ if (!$precision) {
+ return $type;
+ }
+
+ if (str_contains($type, '(')) {
+ return preg_replace('/\(\d+\)/', "($precision)", $type);
+ }
+
+ [$before, $after] = explode(' ', "$type ");
+
+ return trim("$before($precision) $after");
+ }
+
+ /**
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ *
+ * @return T|null
+ */
+ public function convertToPHPValue($value, AbstractPlatform $platform)
+ {
+ $class = $this->getCarbonClassName();
+
+ if ($value === null || is_a($value, $class)) {
+ return $value;
+ }
+
+ if ($value instanceof DateTimeInterface) {
+ return $class::instance($value);
+ }
+
+ $date = null;
+ $error = null;
+
+ try {
+ $date = $class::parse($value);
+ } catch (Exception $exception) {
+ $error = $exception;
+ }
+
+ if (!$date) {
+ throw ConversionException::conversionFailedFormat(
+ $value,
+ $this->getName(),
+ 'Y-m-d H:i:s.u or any format supported by '.$class.'::parse()',
+ $error
+ );
+ }
+
+ return $date;
+ }
+
+ /**
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ *
+ * @return string|null
+ */
+ public function convertToDatabaseValue($value, AbstractPlatform $platform)
+ {
+ if ($value === null) {
+ return $value;
+ }
+
+ if ($value instanceof DateTimeInterface) {
+ return $value->format('Y-m-d H:i:s.u');
+ }
+
+ throw ConversionException::conversionFailedInvalidType(
+ $value,
+ $this->getName(),
+ ['null', 'DateTime', 'Carbon']
+ );
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/DateTimeDefaultPrecision.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/DateTimeDefaultPrecision.php
new file mode 100644
index 0000000..f9744b8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/DateTimeDefaultPrecision.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Thanks to https://github.com/flaushi for his suggestion:
+ * https://github.com/doctrine/dbal/issues/2873#issuecomment-534956358
+ */
+namespace Carbon\Doctrine;
+
+class DateTimeDefaultPrecision
+{
+ private static $precision = 6;
+
+ /**
+ * Change the default Doctrine datetime and datetime_immutable precision.
+ *
+ * @param int $precision
+ */
+ public static function set(int $precision): void
+ {
+ self::$precision = $precision;
+ }
+
+ /**
+ * Get the default Doctrine datetime and datetime_immutable precision.
+ *
+ * @return int
+ */
+ public static function get(): int
+ {
+ return self::$precision;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/DateTimeImmutableType.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/DateTimeImmutableType.php
new file mode 100644
index 0000000..4992710
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/DateTimeImmutableType.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * Thanks to https://github.com/flaushi for his suggestion:
+ * https://github.com/doctrine/dbal/issues/2873#issuecomment-534956358
+ */
+namespace Carbon\Doctrine;
+
+use Carbon\CarbonImmutable;
+use Doctrine\DBAL\Types\VarDateTimeImmutableType;
+
+class DateTimeImmutableType extends VarDateTimeImmutableType implements CarbonDoctrineType
+{
+ /** @use CarbonTypeConverter<CarbonImmutable> */
+ use CarbonTypeConverter;
+
+ /**
+ * @return class-string<CarbonImmutable>
+ */
+ protected function getCarbonClassName(): string
+ {
+ return CarbonImmutable::class;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/DateTimeType.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/DateTimeType.php
new file mode 100644
index 0000000..29b0bb9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/DateTimeType.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * Thanks to https://github.com/flaushi for his suggestion:
+ * https://github.com/doctrine/dbal/issues/2873#issuecomment-534956358
+ */
+namespace Carbon\Doctrine;
+
+use Carbon\Carbon;
+use Doctrine\DBAL\Types\VarDateTimeType;
+
+class DateTimeType extends VarDateTimeType implements CarbonDoctrineType
+{
+ /** @use CarbonTypeConverter<Carbon> */
+ use CarbonTypeConverter;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadComparisonUnitException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadComparisonUnitException.php
new file mode 100644
index 0000000..bc2aa79
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadComparisonUnitException.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+
+class BadComparisonUnitException extends UnitException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $unit
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($unit, $code = 0, Exception $previous = null)
+ {
+ parent::__construct("Bad comparison unit: '$unit'", $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadFluentConstructorException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadFluentConstructorException.php
new file mode 100644
index 0000000..a9f453e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadFluentConstructorException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use BadMethodCallException as BaseBadMethodCallException;
+use Exception;
+
+class BadFluentConstructorException extends BaseBadMethodCallException implements BadMethodCallException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $method
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($method, $code = 0, Exception $previous = null)
+ {
+ parent::__construct(sprintf("Unknown fluent constructor '%s'.", $method), $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadFluentSetterException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadFluentSetterException.php
new file mode 100644
index 0000000..7a28f39
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadFluentSetterException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use BadMethodCallException as BaseBadMethodCallException;
+use Exception;
+
+class BadFluentSetterException extends BaseBadMethodCallException implements BadMethodCallException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $method
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($method, $code = 0, Exception $previous = null)
+ {
+ parent::__construct(sprintf("Unknown fluent setter '%s'", $method), $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadMethodCallException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadMethodCallException.php
new file mode 100644
index 0000000..307a4ee
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/BadMethodCallException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+interface BadMethodCallException extends Exception
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/Exception.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/Exception.php
new file mode 100644
index 0000000..86e8a15
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/Exception.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+interface Exception
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/ImmutableException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/ImmutableException.php
new file mode 100644
index 0000000..5fb1c68
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/ImmutableException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use RuntimeException as BaseRuntimeException;
+
+class ImmutableException extends BaseRuntimeException implements RuntimeException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $value the immutable type/value
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($value, $code = 0, Exception $previous = null)
+ {
+ parent::__construct("$value is immutable.", $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidArgumentException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidArgumentException.php
new file mode 100644
index 0000000..60ed740
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidArgumentException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+interface InvalidArgumentException extends Exception
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidCastException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidCastException.php
new file mode 100644
index 0000000..77466c7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidCastException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class InvalidCastException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($message, $code = 0, Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php
new file mode 100644
index 0000000..f5dbfe2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class InvalidDateException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * The invalid field.
+ *
+ * @var string
+ */
+ private $field;
+
+ /**
+ * The invalid value.
+ *
+ * @var mixed
+ */
+ private $value;
+
+ /**
+ * Constructor.
+ *
+ * @param string $field
+ * @param mixed $value
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($field, $value, $code = 0, Exception $previous = null)
+ {
+ $this->field = $field;
+ $this->value = $value;
+ parent::__construct($field.' : '.$value.' is not a valid value.', $code, $previous);
+ }
+
+ /**
+ * Get the invalid field.
+ *
+ * @return string
+ */
+ public function getField()
+ {
+ return $this->field;
+ }
+
+ /**
+ * Get the invalid value.
+ *
+ * @return mixed
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidFormatException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidFormatException.php
new file mode 100644
index 0000000..dd26a90
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidFormatException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class InvalidFormatException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($message, $code = 0, Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidIntervalException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidIntervalException.php
new file mode 100644
index 0000000..b4c76dc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidIntervalException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class InvalidIntervalException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($message, $code = 0, Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodDateException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodDateException.php
new file mode 100644
index 0000000..abe1aef
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodDateException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class InvalidPeriodDateException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($message, $code = 0, Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodParameterException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodParameterException.php
new file mode 100644
index 0000000..b061ef1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodParameterException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class InvalidPeriodParameterException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($message, $code = 0, Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidTimeZoneException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidTimeZoneException.php
new file mode 100644
index 0000000..03bd8ac
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidTimeZoneException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class InvalidTimeZoneException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($message, $code = 0, Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidTypeException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidTypeException.php
new file mode 100644
index 0000000..bc124a6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidTypeException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class InvalidTypeException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($message, $code = 0, Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/NotACarbonClassException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/NotACarbonClassException.php
new file mode 100644
index 0000000..78ce939
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/NotACarbonClassException.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Carbon\CarbonInterface;
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class NotACarbonClassException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $className
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($className, $code = 0, Exception $previous = null)
+ {
+ parent::__construct(sprintf(
+ 'Given class does not implement %s: %s',
+ CarbonInterface::class,
+ $className
+ ), $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/NotAPeriodException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/NotAPeriodException.php
new file mode 100644
index 0000000..8bdda85
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/NotAPeriodException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class NotAPeriodException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($message, $code = 0, Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/NotLocaleAwareException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/NotLocaleAwareException.php
new file mode 100644
index 0000000..8aab192
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/NotLocaleAwareException.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class NotLocaleAwareException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param mixed $object
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($object, $code = 0, Exception $previous = null)
+ {
+ $dump = \is_object($object) ? \get_class($object) : \gettype($object);
+
+ parent::__construct("$dump does neither implements Symfony\Contracts\Translation\LocaleAwareInterface nor getLocale() method.", $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/OutOfRangeException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/OutOfRangeException.php
new file mode 100644
index 0000000..33cd1b5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/OutOfRangeException.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+// This will extends OutOfRangeException instead of InvalidArgumentException since 3.0.0
+// use OutOfRangeException as BaseOutOfRangeException;
+
+class OutOfRangeException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * The unit or name of the value.
+ *
+ * @var string
+ */
+ private $unit;
+
+ /**
+ * The range minimum.
+ *
+ * @var mixed
+ */
+ private $min;
+
+ /**
+ * The range maximum.
+ *
+ * @var mixed
+ */
+ private $max;
+
+ /**
+ * The invalid value.
+ *
+ * @var mixed
+ */
+ private $value;
+
+ /**
+ * Constructor.
+ *
+ * @param string $unit
+ * @param mixed $min
+ * @param mixed $max
+ * @param mixed $value
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($unit, $min, $max, $value, $code = 0, Exception $previous = null)
+ {
+ $this->unit = $unit;
+ $this->min = $min;
+ $this->max = $max;
+ $this->value = $value;
+
+ parent::__construct("$unit must be between $min and $max, $value given", $code, $previous);
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMax()
+ {
+ return $this->max;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getMin()
+ {
+ return $this->min;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getUnit()
+ {
+ return $this->unit;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/ParseErrorException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/ParseErrorException.php
new file mode 100644
index 0000000..3510b40
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/ParseErrorException.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class ParseErrorException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $expected
+ * @param string $actual
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($expected, $actual, $help = '', $code = 0, Exception $previous = null)
+ {
+ $actual = $actual === '' ? 'data is missing' : "get '$actual'";
+
+ parent::__construct(trim("Format expected $expected but $actual\n$help"), $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/RuntimeException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/RuntimeException.php
new file mode 100644
index 0000000..6ca5f5f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/RuntimeException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+interface RuntimeException extends Exception
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnitException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnitException.php
new file mode 100644
index 0000000..838847b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnitException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class UnitException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($message, $code = 0, Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnitNotConfiguredException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnitNotConfiguredException.php
new file mode 100644
index 0000000..7f8ec9e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnitNotConfiguredException.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+
+class UnitNotConfiguredException extends UnitException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $unit
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($unit, $code = 0, Exception $previous = null)
+ {
+ parent::__construct("Unit $unit have no configuration to get total from other units.", $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownGetterException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownGetterException.php
new file mode 100644
index 0000000..4591d35
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownGetterException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class UnknownGetterException extends BaseInvalidArgumentException implements InvalidArgumentException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $name getter name
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($name, $code = 0, Exception $previous = null)
+ {
+ parent::__construct("Unknown getter '$name'", $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownMethodException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownMethodException.php
new file mode 100644
index 0000000..3646872
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownMethodException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use BadMethodCallException as BaseBadMethodCallException;
+use Exception;
+
+class UnknownMethodException extends BaseBadMethodCallException implements BadMethodCallException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $method
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($method, $code = 0, Exception $previous = null)
+ {
+ parent::__construct("Method $method does not exist.", $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownSetterException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownSetterException.php
new file mode 100644
index 0000000..5020369
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownSetterException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class UnknownSetterException extends BaseInvalidArgumentException implements BadMethodCallException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $name setter name
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($name, $code = 0, Exception $previous = null)
+ {
+ parent::__construct("Unknown setter '$name'", $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownUnitException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownUnitException.php
new file mode 100644
index 0000000..d2f76ee
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownUnitException.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+
+class UnknownUnitException extends UnitException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $unit
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($unit, $code = 0, Exception $previous = null)
+ {
+ parent::__construct("Unknown unit '$unit'.", $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnreachableException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnreachableException.php
new file mode 100644
index 0000000..b38ae12
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Exceptions/UnreachableException.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Exceptions;
+
+use Exception;
+use RuntimeException as BaseRuntimeException;
+
+class UnreachableException extends BaseRuntimeException implements RuntimeException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception|null $previous
+ */
+ public function __construct($message, $code = 0, Exception $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Factory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Factory.php
new file mode 100644
index 0000000..e1d747f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Factory.php
@@ -0,0 +1,304 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use Closure;
+use ReflectionMethod;
+
+/**
+ * A factory to generate Carbon instances with common settings.
+ *
+ * <autodoc generated by `composer phpdoc`>
+ *
+ * @method bool canBeCreatedFromFormat($date, $format) Checks if the (date)time string is in a given format and valid to create a
+ * new instance.
+ * @method Carbon|false create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null) Create a new Carbon instance from a specific date and time.
+ * If any of $year, $month or $day are set to null their now() values will
+ * be used.
+ * If $hour is null it will be set to its now() value and the default
+ * values for $minute and $second will be their now() values.
+ * If $hour is not null then the default values for $minute and $second
+ * will be 0.
+ * @method Carbon createFromDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to now.
+ * @method Carbon|false createFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format.
+ * @method Carbon|false createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null) Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
+ * @method Carbon|false createFromLocaleFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific format and a string in a given language.
+ * @method Carbon|false createFromLocaleIsoFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific ISO format and a string in a given language.
+ * @method Carbon createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null) Create a Carbon instance from just a time. The date portion is set to today.
+ * @method Carbon createFromTimeString($time, $tz = null) Create a Carbon instance from a time string. The date portion is set to today.
+ * @method Carbon createFromTimestamp($timestamp, $tz = null) Create a Carbon instance from a timestamp and set the timezone (use default one if not specified).
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ * @method Carbon createFromTimestampMs($timestamp, $tz = null) Create a Carbon instance from a timestamp in milliseconds.
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ * @method Carbon createFromTimestampMsUTC($timestamp) Create a Carbon instance from a timestamp in milliseconds.
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ * @method Carbon createFromTimestampUTC($timestamp) Create a Carbon instance from an timestamp keeping the timezone to UTC.
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ * @method Carbon createMidnightDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to midnight.
+ * @method Carbon|false createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null) Create a new safe Carbon instance from a specific date and time.
+ * If any of $year, $month or $day are set to null their now() values will
+ * be used.
+ * If $hour is null it will be set to its now() value and the default
+ * values for $minute and $second will be their now() values.
+ * If $hour is not null then the default values for $minute and $second
+ * will be 0.
+ * If one of the set values is not valid, an InvalidDateException
+ * will be thrown.
+ * @method CarbonInterface createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null) Create a new Carbon instance from a specific date and time using strict validation.
+ * @method Carbon disableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @method Carbon enableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @method mixed executeWithLocale($locale, $func) Set the current locale to the given, execute the passed function, reset the locale to previous one,
+ * then return the result of the closure (or null if the closure was void).
+ * @method Carbon fromSerialized($value) Create an instance from a serialized string.
+ * @method void genericMacro($macro, $priority = 0) Register a custom macro.
+ * @method array getAvailableLocales() Returns the list of internally available locales and already loaded custom locales.
+ * (It will ignore custom translator dynamic loading.)
+ * @method Language[] getAvailableLocalesInfo() Returns list of Language object for each available locale. This object allow you to get the ISO name, native
+ * name, region and variant of the locale.
+ * @method array getDays() Get the days of the week
+ * @method string|null getFallbackLocale() Get the fallback locale.
+ * @method array getFormatsToIsoReplacements() List of replacements from date() format to isoFormat().
+ * @method int getHumanDiffOptions() Return default humanDiff() options (merged flags as integer).
+ * @method array getIsoUnits() Returns list of locale units for ISO formatting.
+ * @method Carbon getLastErrors() {@inheritdoc}
+ * @method string getLocale() Get the current translator locale.
+ * @method callable|null getMacro($name) Get the raw callable macro registered globally for a given name.
+ * @method int getMidDayAt() get midday/noon hour
+ * @method Closure|Carbon getTestNow() Get the Carbon instance (real or mock) to be returned when a "now"
+ * instance is created.
+ * @method string getTimeFormatByPrecision($unitPrecision) Return a format from H:i to H:i:s.u according to given unit precision.
+ * @method string getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null) Returns raw translation message for a given key.
+ * @method \Symfony\Component\Translation\TranslatorInterface getTranslator() Get the default translator instance in use.
+ * @method int getWeekEndsAt() Get the last day of week
+ * @method int getWeekStartsAt() Get the first day of week
+ * @method array getWeekendDays() Get weekend days
+ * @method bool hasFormat($date, $format) Checks if the (date)time string is in a given format.
+ * @method bool hasFormatWithModifiers($date, $format) Checks if the (date)time string is in a given format.
+ * @method bool hasMacro($name) Checks if macro is registered globally.
+ * @method bool hasRelativeKeywords($time) Determine if a time string will produce a relative date.
+ * @method bool hasTestNow() Determine if there is a valid test instance set. A valid test instance
+ * is anything that is not null.
+ * @method Carbon instance($date) Create a Carbon instance from a DateTime one.
+ * @method bool isImmutable() Returns true if the current class/instance is immutable.
+ * @method bool isModifiableUnit($unit) Returns true if a property can be changed via setter.
+ * @method bool isMutable() Returns true if the current class/instance is mutable.
+ * @method bool isStrictModeEnabled() Returns true if the strict mode is globally in use, false else.
+ * (It can be overridden in specific instances.)
+ * @method bool localeHasDiffOneDayWords($locale) Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
+ * Support is considered enabled if the 3 words are translated in the given locale.
+ * @method bool localeHasDiffSyntax($locale) Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
+ * Support is considered enabled if the 4 sentences are translated in the given locale.
+ * @method bool localeHasDiffTwoDayWords($locale) Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
+ * Support is considered enabled if the 2 words are translated in the given locale.
+ * @method bool localeHasPeriodSyntax($locale) Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
+ * Support is considered enabled if the 4 sentences are translated in the given locale.
+ * @method bool localeHasShortUnits($locale) Returns true if the given locale is internally supported and has short-units support.
+ * Support is considered enabled if either year, day or hour has a short variant translated.
+ * @method void macro($name, $macro) Register a custom macro.
+ * @method Carbon|null make($var) Make a Carbon instance from given variable if possible.
+ * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
+ * and recurrences). Throw an exception for invalid format, but otherwise return null.
+ * @method Carbon maxValue() Create a Carbon instance for the greatest supported date.
+ * @method Carbon minValue() Create a Carbon instance for the lowest supported date.
+ * @method void mixin($mixin) Mix another object into the class.
+ * @method Carbon now($tz = null) Get a Carbon instance for the current date and time.
+ * @method Carbon parse($time = null, $tz = null) Create a carbon instance from a string.
+ * This is an alias for the constructor that allows better fluent syntax
+ * as it allows you to do Carbon::parse('Monday next week')->fn() rather
+ * than (new Carbon('Monday next week'))->fn().
+ * @method Carbon parseFromLocale($time, $locale = null, $tz = null) Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
+ * @method string pluralUnit(string $unit) Returns standardized plural of a given singular/plural unit name (in English).
+ * @method Carbon|false rawCreateFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format.
+ * @method Carbon rawParse($time = null, $tz = null) Create a carbon instance from a string.
+ * This is an alias for the constructor that allows better fluent syntax
+ * as it allows you to do Carbon::parse('Monday next week')->fn() rather
+ * than (new Carbon('Monday next week'))->fn().
+ * @method Carbon resetMacros() Remove all macros and generic macros.
+ * @method void resetMonthsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @method void resetToStringFormat() Reset the format used to the default when type juggling a Carbon instance to a string
+ * @method void resetYearsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @method void serializeUsing($callback) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather transform Carbon object before the serialization.
+ * JSON serialize all Carbon instances using the given callback.
+ * @method Carbon setFallbackLocale($locale) Set the fallback locale.
+ * @method Carbon setHumanDiffOptions($humanDiffOptions) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @method bool setLocale($locale) Set the current translator locale and indicate if the source locale file exists.
+ * Pass 'auto' as locale to use closest language from the current LC_TIME locale.
+ * @method void setMidDayAt($hour) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather consider mid-day is always 12pm, then if you need to test if it's an other
+ * hour, test it explicitly:
+ * $date->format('G') == 13
+ * or to set explicitly to a given hour:
+ * $date->setTime(13, 0, 0, 0)
+ * Set midday/noon hour
+ * @method Carbon setTestNow($testNow = null) Set a Carbon instance (real or mock) to be returned when a "now"
+ * instance is created. The provided instance will be returned
+ * specifically under the following conditions:
+ * - A call to the static now() method, ex. Carbon::now()
+ * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
+ * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
+ * - When a string containing the desired time is passed to Carbon::parse().
+ * Note the timezone parameter was left out of the examples above and
+ * has no affect as the mock value will be returned regardless of its value.
+ * To clear the test instance call this method using the default
+ * parameter of null.
+ * /!\ Use this method for unit tests only.
+ * @method void setToStringFormat($format) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather let Carbon object being casted to string with DEFAULT_TO_STRING_FORMAT, and
+ * use other method or custom format passed to format() method if you need to dump an other string
+ * format.
+ * Set the default format used when type juggling a Carbon instance to a string
+ * @method void setTranslator(\Symfony\Component\Translation\TranslatorInterface $translator) Set the default translator instance to use.
+ * @method Carbon setUtf8($utf8) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use UTF-8 language packages on every machine.
+ * Set if UTF8 will be used for localized date/time.
+ * @method void setWeekEndsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek
+ * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the
+ * start of week according to current locale selected and implicitly the end of week.
+ * Set the last day of week
+ * @method void setWeekStartsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the
+ * 'first_day_of_week' locale setting to change the start of week according to current locale
+ * selected and implicitly the end of week.
+ * Set the first day of week
+ * @method void setWeekendDays($days) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather consider week-end is always saturday and sunday, and if you have some custom
+ * week-end days to handle, give to those days an other name and create a macro for them:
+ * ```
+ * Carbon::macro('isDayOff', function ($date) {
+ * return $date->isSunday() || $date->isMonday();
+ * });
+ * Carbon::macro('isNotDayOff', function ($date) {
+ * return !$date->isDayOff();
+ * });
+ * if ($someDate->isDayOff()) ...
+ * if ($someDate->isNotDayOff()) ...
+ * // Add 5 not-off days
+ * $count = 5;
+ * while ($someDate->isDayOff() || ($count-- > 0)) {
+ * $someDate->addDay();
+ * }
+ * ```
+ * Set weekend days
+ * @method bool shouldOverflowMonths() Get the month overflow global behavior (can be overridden in specific instances).
+ * @method bool shouldOverflowYears() Get the month overflow global behavior (can be overridden in specific instances).
+ * @method string singularUnit(string $unit) Returns standardized singular of a given singular/plural unit name (in English).
+ * @method Carbon today($tz = null) Create a Carbon instance for today.
+ * @method Carbon tomorrow($tz = null) Create a Carbon instance for tomorrow.
+ * @method string translateTimeString($timeString, $from = null, $to = null, $mode = CarbonInterface::TRANSLATE_ALL) Translate a time string from a locale to an other.
+ * @method string translateWith(\Symfony\Component\Translation\TranslatorInterface $translator, string $key, array $parameters = [], $number = null) Translate using translation string or callback available.
+ * @method void useMonthsOverflow($monthsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @method Carbon useStrictMode($strictModeEnabled = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @method void useYearsOverflow($yearsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @method mixed withTestNow($testNow = null, $callback = null) Temporarily sets a static date to be used within the callback.
+ * Using setTestNow to set the date, executing the callback, then
+ * clearing the test instance.
+ * /!\ Use this method for unit tests only.
+ * @method Carbon yesterday($tz = null) Create a Carbon instance for yesterday.
+ *
+ * </autodoc>
+ */
+class Factory
+{
+ protected $className = Carbon::class;
+
+ protected $settings = [];
+
+ public function __construct(array $settings = [], ?string $className = null)
+ {
+ if ($className) {
+ $this->className = $className;
+ }
+
+ $this->settings = $settings;
+ }
+
+ public function getClassName()
+ {
+ return $this->className;
+ }
+
+ public function setClassName(string $className)
+ {
+ $this->className = $className;
+
+ return $this;
+ }
+
+ public function className(string $className = null)
+ {
+ return $className === null ? $this->getClassName() : $this->setClassName($className);
+ }
+
+ public function getSettings()
+ {
+ return $this->settings;
+ }
+
+ public function setSettings(array $settings)
+ {
+ $this->settings = $settings;
+
+ return $this;
+ }
+
+ public function settings(array $settings = null)
+ {
+ return $settings === null ? $this->getSettings() : $this->setSettings($settings);
+ }
+
+ public function mergeSettings(array $settings)
+ {
+ $this->settings = array_merge($this->settings, $settings);
+
+ return $this;
+ }
+
+ public function __call($name, $arguments)
+ {
+ $method = new ReflectionMethod($this->className, $name);
+ $settings = $this->settings;
+
+ if ($settings && isset($settings['timezone'])) {
+ $tzParameters = array_filter($method->getParameters(), function ($parameter) {
+ return \in_array($parameter->getName(), ['tz', 'timezone'], true);
+ });
+
+ if (\count($tzParameters)) {
+ array_splice($arguments, key($tzParameters), 0, [$settings['timezone']]);
+ unset($settings['timezone']);
+ }
+ }
+
+ $result = $this->className::$name(...$arguments);
+
+ return $result instanceof CarbonInterface && !empty($settings)
+ ? $result->settings($settings)
+ : $result;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/FactoryImmutable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/FactoryImmutable.php
new file mode 100644
index 0000000..3aa286c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/FactoryImmutable.php
@@ -0,0 +1,228 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use Closure;
+
+/**
+ * A factory to generate CarbonImmutable instances with common settings.
+ *
+ * <autodoc generated by `composer phpdoc`>
+ *
+ * @method bool canBeCreatedFromFormat($date, $format) Checks if the (date)time string is in a given format and valid to create a
+ * new instance.
+ * @method CarbonImmutable|false create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null) Create a new Carbon instance from a specific date and time.
+ * If any of $year, $month or $day are set to null their now() values will
+ * be used.
+ * If $hour is null it will be set to its now() value and the default
+ * values for $minute and $second will be their now() values.
+ * If $hour is not null then the default values for $minute and $second
+ * will be 0.
+ * @method CarbonImmutable createFromDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to now.
+ * @method CarbonImmutable|false createFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format.
+ * @method CarbonImmutable|false createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null) Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
+ * @method CarbonImmutable|false createFromLocaleFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific format and a string in a given language.
+ * @method CarbonImmutable|false createFromLocaleIsoFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific ISO format and a string in a given language.
+ * @method CarbonImmutable createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null) Create a Carbon instance from just a time. The date portion is set to today.
+ * @method CarbonImmutable createFromTimeString($time, $tz = null) Create a Carbon instance from a time string. The date portion is set to today.
+ * @method CarbonImmutable createFromTimestamp($timestamp, $tz = null) Create a Carbon instance from a timestamp and set the timezone (use default one if not specified).
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ * @method CarbonImmutable createFromTimestampMs($timestamp, $tz = null) Create a Carbon instance from a timestamp in milliseconds.
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ * @method CarbonImmutable createFromTimestampMsUTC($timestamp) Create a Carbon instance from a timestamp in milliseconds.
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ * @method CarbonImmutable createFromTimestampUTC($timestamp) Create a Carbon instance from an timestamp keeping the timezone to UTC.
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ * @method CarbonImmutable createMidnightDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to midnight.
+ * @method CarbonImmutable|false createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null) Create a new safe Carbon instance from a specific date and time.
+ * If any of $year, $month or $day are set to null their now() values will
+ * be used.
+ * If $hour is null it will be set to its now() value and the default
+ * values for $minute and $second will be their now() values.
+ * If $hour is not null then the default values for $minute and $second
+ * will be 0.
+ * If one of the set values is not valid, an InvalidDateException
+ * will be thrown.
+ * @method CarbonInterface createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null) Create a new Carbon instance from a specific date and time using strict validation.
+ * @method CarbonImmutable disableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @method CarbonImmutable enableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @method mixed executeWithLocale($locale, $func) Set the current locale to the given, execute the passed function, reset the locale to previous one,
+ * then return the result of the closure (or null if the closure was void).
+ * @method CarbonImmutable fromSerialized($value) Create an instance from a serialized string.
+ * @method void genericMacro($macro, $priority = 0) Register a custom macro.
+ * @method array getAvailableLocales() Returns the list of internally available locales and already loaded custom locales.
+ * (It will ignore custom translator dynamic loading.)
+ * @method Language[] getAvailableLocalesInfo() Returns list of Language object for each available locale. This object allow you to get the ISO name, native
+ * name, region and variant of the locale.
+ * @method array getDays() Get the days of the week
+ * @method string|null getFallbackLocale() Get the fallback locale.
+ * @method array getFormatsToIsoReplacements() List of replacements from date() format to isoFormat().
+ * @method int getHumanDiffOptions() Return default humanDiff() options (merged flags as integer).
+ * @method array getIsoUnits() Returns list of locale units for ISO formatting.
+ * @method CarbonImmutable getLastErrors() {@inheritdoc}
+ * @method string getLocale() Get the current translator locale.
+ * @method callable|null getMacro($name) Get the raw callable macro registered globally for a given name.
+ * @method int getMidDayAt() get midday/noon hour
+ * @method Closure|CarbonImmutable getTestNow() Get the Carbon instance (real or mock) to be returned when a "now"
+ * instance is created.
+ * @method string getTimeFormatByPrecision($unitPrecision) Return a format from H:i to H:i:s.u according to given unit precision.
+ * @method string getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null) Returns raw translation message for a given key.
+ * @method \Symfony\Component\Translation\TranslatorInterface getTranslator() Get the default translator instance in use.
+ * @method int getWeekEndsAt() Get the last day of week
+ * @method int getWeekStartsAt() Get the first day of week
+ * @method array getWeekendDays() Get weekend days
+ * @method bool hasFormat($date, $format) Checks if the (date)time string is in a given format.
+ * @method bool hasFormatWithModifiers($date, $format) Checks if the (date)time string is in a given format.
+ * @method bool hasMacro($name) Checks if macro is registered globally.
+ * @method bool hasRelativeKeywords($time) Determine if a time string will produce a relative date.
+ * @method bool hasTestNow() Determine if there is a valid test instance set. A valid test instance
+ * is anything that is not null.
+ * @method CarbonImmutable instance($date) Create a Carbon instance from a DateTime one.
+ * @method bool isImmutable() Returns true if the current class/instance is immutable.
+ * @method bool isModifiableUnit($unit) Returns true if a property can be changed via setter.
+ * @method bool isMutable() Returns true if the current class/instance is mutable.
+ * @method bool isStrictModeEnabled() Returns true if the strict mode is globally in use, false else.
+ * (It can be overridden in specific instances.)
+ * @method bool localeHasDiffOneDayWords($locale) Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
+ * Support is considered enabled if the 3 words are translated in the given locale.
+ * @method bool localeHasDiffSyntax($locale) Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
+ * Support is considered enabled if the 4 sentences are translated in the given locale.
+ * @method bool localeHasDiffTwoDayWords($locale) Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
+ * Support is considered enabled if the 2 words are translated in the given locale.
+ * @method bool localeHasPeriodSyntax($locale) Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
+ * Support is considered enabled if the 4 sentences are translated in the given locale.
+ * @method bool localeHasShortUnits($locale) Returns true if the given locale is internally supported and has short-units support.
+ * Support is considered enabled if either year, day or hour has a short variant translated.
+ * @method void macro($name, $macro) Register a custom macro.
+ * @method CarbonImmutable|null make($var) Make a Carbon instance from given variable if possible.
+ * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
+ * and recurrences). Throw an exception for invalid format, but otherwise return null.
+ * @method CarbonImmutable maxValue() Create a Carbon instance for the greatest supported date.
+ * @method CarbonImmutable minValue() Create a Carbon instance for the lowest supported date.
+ * @method void mixin($mixin) Mix another object into the class.
+ * @method CarbonImmutable now($tz = null) Get a Carbon instance for the current date and time.
+ * @method CarbonImmutable parse($time = null, $tz = null) Create a carbon instance from a string.
+ * This is an alias for the constructor that allows better fluent syntax
+ * as it allows you to do Carbon::parse('Monday next week')->fn() rather
+ * than (new Carbon('Monday next week'))->fn().
+ * @method CarbonImmutable parseFromLocale($time, $locale = null, $tz = null) Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
+ * @method string pluralUnit(string $unit) Returns standardized plural of a given singular/plural unit name (in English).
+ * @method CarbonImmutable|false rawCreateFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format.
+ * @method CarbonImmutable rawParse($time = null, $tz = null) Create a carbon instance from a string.
+ * This is an alias for the constructor that allows better fluent syntax
+ * as it allows you to do Carbon::parse('Monday next week')->fn() rather
+ * than (new Carbon('Monday next week'))->fn().
+ * @method CarbonImmutable resetMacros() Remove all macros and generic macros.
+ * @method void resetMonthsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @method void resetToStringFormat() Reset the format used to the default when type juggling a Carbon instance to a string
+ * @method void resetYearsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @method void serializeUsing($callback) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather transform Carbon object before the serialization.
+ * JSON serialize all Carbon instances using the given callback.
+ * @method CarbonImmutable setFallbackLocale($locale) Set the fallback locale.
+ * @method CarbonImmutable setHumanDiffOptions($humanDiffOptions) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @method bool setLocale($locale) Set the current translator locale and indicate if the source locale file exists.
+ * Pass 'auto' as locale to use closest language from the current LC_TIME locale.
+ * @method void setMidDayAt($hour) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather consider mid-day is always 12pm, then if you need to test if it's an other
+ * hour, test it explicitly:
+ * $date->format('G') == 13
+ * or to set explicitly to a given hour:
+ * $date->setTime(13, 0, 0, 0)
+ * Set midday/noon hour
+ * @method CarbonImmutable setTestNow($testNow = null) Set a Carbon instance (real or mock) to be returned when a "now"
+ * instance is created. The provided instance will be returned
+ * specifically under the following conditions:
+ * - A call to the static now() method, ex. Carbon::now()
+ * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
+ * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
+ * - When a string containing the desired time is passed to Carbon::parse().
+ * Note the timezone parameter was left out of the examples above and
+ * has no affect as the mock value will be returned regardless of its value.
+ * To clear the test instance call this method using the default
+ * parameter of null.
+ * /!\ Use this method for unit tests only.
+ * @method void setToStringFormat($format) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather let Carbon object being casted to string with DEFAULT_TO_STRING_FORMAT, and
+ * use other method or custom format passed to format() method if you need to dump an other string
+ * format.
+ * Set the default format used when type juggling a Carbon instance to a string
+ * @method void setTranslator(\Symfony\Component\Translation\TranslatorInterface $translator) Set the default translator instance to use.
+ * @method CarbonImmutable setUtf8($utf8) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use UTF-8 language packages on every machine.
+ * Set if UTF8 will be used for localized date/time.
+ * @method void setWeekEndsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek
+ * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the
+ * start of week according to current locale selected and implicitly the end of week.
+ * Set the last day of week
+ * @method void setWeekStartsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the
+ * 'first_day_of_week' locale setting to change the start of week according to current locale
+ * selected and implicitly the end of week.
+ * Set the first day of week
+ * @method void setWeekendDays($days) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather consider week-end is always saturday and sunday, and if you have some custom
+ * week-end days to handle, give to those days an other name and create a macro for them:
+ * ```
+ * Carbon::macro('isDayOff', function ($date) {
+ * return $date->isSunday() || $date->isMonday();
+ * });
+ * Carbon::macro('isNotDayOff', function ($date) {
+ * return !$date->isDayOff();
+ * });
+ * if ($someDate->isDayOff()) ...
+ * if ($someDate->isNotDayOff()) ...
+ * // Add 5 not-off days
+ * $count = 5;
+ * while ($someDate->isDayOff() || ($count-- > 0)) {
+ * $someDate->addDay();
+ * }
+ * ```
+ * Set weekend days
+ * @method bool shouldOverflowMonths() Get the month overflow global behavior (can be overridden in specific instances).
+ * @method bool shouldOverflowYears() Get the month overflow global behavior (can be overridden in specific instances).
+ * @method string singularUnit(string $unit) Returns standardized singular of a given singular/plural unit name (in English).
+ * @method CarbonImmutable today($tz = null) Create a Carbon instance for today.
+ * @method CarbonImmutable tomorrow($tz = null) Create a Carbon instance for tomorrow.
+ * @method string translateTimeString($timeString, $from = null, $to = null, $mode = CarbonInterface::TRANSLATE_ALL) Translate a time string from a locale to an other.
+ * @method string translateWith(\Symfony\Component\Translation\TranslatorInterface $translator, string $key, array $parameters = [], $number = null) Translate using translation string or callback available.
+ * @method void useMonthsOverflow($monthsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @method CarbonImmutable useStrictMode($strictModeEnabled = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @method void useYearsOverflow($yearsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @method mixed withTestNow($testNow = null, $callback = null) Temporarily sets a static date to be used within the callback.
+ * Using setTestNow to set the date, executing the callback, then
+ * clearing the test instance.
+ * /!\ Use this method for unit tests only.
+ * @method CarbonImmutable yesterday($tz = null) Create a Carbon instance for yesterday.
+ *
+ * </autodoc>
+ */
+class FactoryImmutable extends Factory
+{
+ protected $className = CarbonImmutable::class;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa.php
new file mode 100644
index 0000000..f3431e4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/aa_DJ.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_DJ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_DJ.php
new file mode 100644
index 0000000..c6e23c0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_DJ.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
+ 'months_short' => ['qun', 'nah', 'cig', 'agd', 'cax', 'qas', 'qad', 'leq', 'way', 'dit', 'xim', 'kax'],
+ 'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'],
+ 'weekdays_short' => ['aca', 'etl', 'tal', 'arb', 'kam', 'gum', 'sab'],
+ 'weekdays_min' => ['aca', 'etl', 'tal', 'arb', 'kam', 'gum', 'sab'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['saaku', 'carra'],
+
+ 'year' => ':count gaqambo', // less reliable
+ 'y' => ':count gaqambo', // less reliable
+ 'a_year' => ':count gaqambo', // less reliable
+
+ 'month' => ':count àlsa',
+ 'm' => ':count àlsa',
+ 'a_month' => ':count àlsa',
+
+ 'day' => ':count saaku', // less reliable
+ 'd' => ':count saaku', // less reliable
+ 'a_day' => ':count saaku', // less reliable
+
+ 'hour' => ':count ayti', // less reliable
+ 'h' => ':count ayti', // less reliable
+ 'a_hour' => ':count ayti', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_ER.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_ER.php
new file mode 100644
index 0000000..f8f395b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_ER.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Qunxa Garablu', 'Naharsi Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Leqeeni', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
+ 'months_short' => ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
+ 'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'],
+ 'weekdays_short' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
+ 'weekdays_min' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['saaku', 'carra'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_ER@saaho.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_ER@saaho.php
new file mode 100644
index 0000000..6461225
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_ER@saaho.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Qunxa Garablu', 'Naharsi Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Leqeeni', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
+ 'months_short' => ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
+ 'weekdays' => ['Naba Sambat', 'Sani', 'Salus', 'Rabuq', 'Camus', 'Jumqata', 'Qunxa Sambat'],
+ 'weekdays_short' => ['Nab', 'San', 'Sal', 'Rab', 'Cam', 'Jum', 'Qun'],
+ 'weekdays_min' => ['Nab', 'San', 'Sal', 'Rab', 'Cam', 'Jum', 'Qun'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['saaku', 'carra'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_ET.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_ET.php
new file mode 100644
index 0000000..e55e591
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/aa_ET.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
+ 'months_short' => ['Qun', 'Kud', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
+ 'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'],
+ 'weekdays_short' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
+ 'weekdays_min' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['saaku', 'carra'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/af.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/af.php
new file mode 100644
index 0000000..27771d7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/af.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - JD Isaacks
+ * - Pierre du Plessis
+ */
+return [
+ 'year' => ':count jaar',
+ 'a_year' => '\'n jaar|:count jaar',
+ 'y' => ':count j.',
+ 'month' => ':count maand|:count maande',
+ 'a_month' => '\'n maand|:count maande',
+ 'm' => ':count maa.',
+ 'week' => ':count week|:count weke',
+ 'a_week' => '\'n week|:count weke',
+ 'w' => ':count w.',
+ 'day' => ':count dag|:count dae',
+ 'a_day' => '\'n dag|:count dae',
+ 'd' => ':count d.',
+ 'hour' => ':count uur',
+ 'a_hour' => '\'n uur|:count uur',
+ 'h' => ':count u.',
+ 'minute' => ':count minuut|:count minute',
+ 'a_minute' => '\'n minuut|:count minute',
+ 'min' => ':count min.',
+ 'second' => ':count sekond|:count sekondes',
+ 'a_second' => '\'n paar sekondes|:count sekondes',
+ 's' => ':count s.',
+ 'ago' => ':time gelede',
+ 'from_now' => 'oor :time',
+ 'after' => ':time na',
+ 'before' => ':time voor',
+ 'diff_now' => 'Nou',
+ 'diff_today' => 'Vandag',
+ 'diff_today_regexp' => 'Vandag(?:\\s+om)?',
+ 'diff_yesterday' => 'Gister',
+ 'diff_yesterday_regexp' => 'Gister(?:\\s+om)?',
+ 'diff_tomorrow' => 'Môre',
+ 'diff_tomorrow_regexp' => 'Môre(?:\\s+om)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Vandag om] LT',
+ 'nextDay' => '[Môre om] LT',
+ 'nextWeek' => 'dddd [om] LT',
+ 'lastDay' => '[Gister om] LT',
+ 'lastWeek' => '[Laas] dddd [om] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de');
+ },
+ 'meridiem' => ['VM', 'NM'],
+ 'months' => ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'],
+ 'months_short' => ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'weekdays' => ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
+ 'weekdays_short' => ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'],
+ 'weekdays_min' => ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' en '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/af_NA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/af_NA.php
new file mode 100644
index 0000000..40d8d86
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/af_NA.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/af.php', [
+ 'meridiem' => ['v', 'n'],
+ 'weekdays' => ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
+ 'weekdays_short' => ['So.', 'Ma.', 'Di.', 'Wo.', 'Do.', 'Vr.', 'Sa.'],
+ 'weekdays_min' => ['So.', 'Ma.', 'Di.', 'Wo.', 'Do.', 'Vr.', 'Sa.'],
+ 'months' => ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'],
+ 'months_short' => ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.', 'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Des.'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'DD MMM YYYY',
+ 'LLL' => 'DD MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, DD MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/af_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/af_ZA.php
new file mode 100644
index 0000000..93f4c83
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/af_ZA.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/af.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/agq.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/agq.php
new file mode 100644
index 0000000..58c7a11
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/agq.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['a.g', 'a.k'],
+ 'weekdays' => ['tsuʔntsɨ', 'tsuʔukpà', 'tsuʔughɔe', 'tsuʔutɔ̀mlò', 'tsuʔumè', 'tsuʔughɨ̂m', 'tsuʔndzɨkɔʔɔ'],
+ 'weekdays_short' => ['nts', 'kpa', 'ghɔ', 'tɔm', 'ume', 'ghɨ', 'dzk'],
+ 'weekdays_min' => ['nts', 'kpa', 'ghɔ', 'tɔm', 'ume', 'ghɨ', 'dzk'],
+ 'months' => ['ndzɔ̀ŋɔ̀nùm', 'ndzɔ̀ŋɔ̀kƗ̀zùʔ', 'ndzɔ̀ŋɔ̀tƗ̀dʉ̀ghà', 'ndzɔ̀ŋɔ̀tǎafʉ̄ghā', 'ndzɔ̀ŋèsèe', 'ndzɔ̀ŋɔ̀nzùghò', 'ndzɔ̀ŋɔ̀dùmlo', 'ndzɔ̀ŋɔ̀kwîfɔ̀e', 'ndzɔ̀ŋɔ̀tƗ̀fʉ̀ghàdzughù', 'ndzɔ̀ŋɔ̀ghǔuwelɔ̀m', 'ndzɔ̀ŋɔ̀chwaʔàkaa wo', 'ndzɔ̀ŋèfwòo'],
+ 'months_short' => ['nùm', 'kɨz', 'tɨd', 'taa', 'see', 'nzu', 'dum', 'fɔe', 'dzu', 'lɔm', 'kaa', 'fwo'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/agr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/agr.php
new file mode 100644
index 0000000..8f036ae
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/agr.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/agr_PE.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/agr_PE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/agr_PE.php
new file mode 100644
index 0000000..54a326a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/agr_PE.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - somosazucar.org libc-alpha@sourceware.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['Petsatin', 'Kupitin', 'Uyaitin', 'Tayutin', 'Kegketin', 'Tegmatin', 'Kuntutin', 'Yagkujutin', 'Daiktatin', 'Ipamtatin', 'Shinutin', 'Sakamtin'],
+ 'months_short' => ['Pet', 'Kup', 'Uya', 'Tay', 'Keg', 'Teg', 'Kun', 'Yag', 'Dait', 'Ipam', 'Shin', 'Sak'],
+ 'weekdays' => ['Tuntuamtin', 'Achutin', 'Kugkuktin', 'Saketin', 'Shimpitin', 'Imaptin', 'Bataetin'],
+ 'weekdays_short' => ['Tun', 'Ach', 'Kug', 'Sak', 'Shim', 'Im', 'Bat'],
+ 'weekdays_min' => ['Tun', 'Ach', 'Kug', 'Sak', 'Shim', 'Im', 'Bat'],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 7,
+ 'meridiem' => ['VM', 'NM'],
+
+ 'year' => ':count yaya', // less reliable
+ 'y' => ':count yaya', // less reliable
+ 'a_year' => ':count yaya', // less reliable
+
+ 'month' => ':count nantu', // less reliable
+ 'm' => ':count nantu', // less reliable
+ 'a_month' => ':count nantu', // less reliable
+
+ 'day' => ':count nayaim', // less reliable
+ 'd' => ':count nayaim', // less reliable
+ 'a_day' => ':count nayaim', // less reliable
+
+ 'hour' => ':count kuwiš', // less reliable
+ 'h' => ':count kuwiš', // less reliable
+ 'a_hour' => ':count kuwiš', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ak.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ak.php
new file mode 100644
index 0000000..5a64be3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ak.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ak_GH.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ak_GH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ak_GH.php
new file mode 100644
index 0000000..1381946
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ak_GH.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY/MM/DD',
+ ],
+ 'months' => ['Sanda-Ɔpɛpɔn', 'Kwakwar-Ɔgyefuo', 'Ebɔw-Ɔbenem', 'Ebɔbira-Oforisuo', 'Esusow Aketseaba-Kɔtɔnimba', 'Obirade-Ayɛwohomumu', 'Ayɛwoho-Kitawonsa', 'Difuu-Ɔsandaa', 'Fankwa-Ɛbɔ', 'Ɔbɛsɛ-Ahinime', 'Ɔberɛfɛw-Obubuo', 'Mumu-Ɔpɛnimba'],
+ 'months_short' => ['S-Ɔ', 'K-Ɔ', 'E-Ɔ', 'E-O', 'E-K', 'O-A', 'A-K', 'D-Ɔ', 'F-Ɛ', 'Ɔ-A', 'Ɔ-O', 'M-Ɔ'],
+ 'weekdays' => ['Kwesida', 'Dwowda', 'Benada', 'Wukuda', 'Yawda', 'Fida', 'Memeneda'],
+ 'weekdays_short' => ['Kwe', 'Dwo', 'Ben', 'Wuk', 'Yaw', 'Fia', 'Mem'],
+ 'weekdays_min' => ['Kwe', 'Dwo', 'Ben', 'Wuk', 'Yaw', 'Fia', 'Mem'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['AN', 'EW'],
+
+ 'year' => ':count afe',
+ 'y' => ':count afe',
+ 'a_year' => ':count afe',
+
+ 'month' => ':count bosume',
+ 'm' => ':count bosume',
+ 'a_month' => ':count bosume',
+
+ 'day' => ':count ɛda',
+ 'd' => ':count ɛda',
+ 'a_day' => ':count ɛda',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/am.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/am.php
new file mode 100644
index 0000000..63bf72d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/am.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/am_ET.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/am_ET.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/am_ET.php
new file mode 100644
index 0000000..ece8062
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/am_ET.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕሪል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክቶበር', 'ኖቬምበር', 'ዲሴምበር'],
+ 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
+ 'weekdays' => ['እሑድ', 'ሰኞ', 'ማክሰኞ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
+ 'weekdays_short' => ['እሑድ', 'ሰኞ ', 'ማክሰ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
+ 'weekdays_min' => ['እሑድ', 'ሰኞ ', 'ማክሰ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ጡዋት', 'ከሰዓት'],
+
+ 'year' => ':count አመት',
+ 'y' => ':count አመት',
+ 'a_year' => ':count አመት',
+
+ 'month' => ':count ወር',
+ 'm' => ':count ወር',
+ 'a_month' => ':count ወር',
+
+ 'week' => ':count ሳምንት',
+ 'w' => ':count ሳምንት',
+ 'a_week' => ':count ሳምንት',
+
+ 'day' => ':count ቀን',
+ 'd' => ':count ቀን',
+ 'a_day' => ':count ቀን',
+
+ 'hour' => ':count ሰዓት',
+ 'h' => ':count ሰዓት',
+ 'a_hour' => ':count ሰዓት',
+
+ 'minute' => ':count ደቂቃ',
+ 'min' => ':count ደቂቃ',
+ 'a_minute' => ':count ደቂቃ',
+
+ 'second' => ':count ሴኮንድ',
+ 's' => ':count ሴኮንድ',
+ 'a_second' => ':count ሴኮንድ',
+
+ 'ago' => 'ከ:time በፊት',
+ 'from_now' => 'በ:time ውስጥ',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/an.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/an.php
new file mode 100644
index 0000000..565abf2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/an.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/an_ES.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/an_ES.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/an_ES.php
new file mode 100644
index 0000000..faf8ae0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/an_ES.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Softaragones Jordi Mallach Pérez, Juan Pablo Martínez bug-glibc-locales@gnu.org, softaragones@softaragones.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['chinero', 'febrero', 'marzo', 'abril', 'mayo', 'chunyo', 'chuliol', 'agosto', 'setiembre', 'octubre', 'noviembre', 'aviento'],
+ 'months_short' => ['chi', 'feb', 'mar', 'abr', 'may', 'chn', 'chl', 'ago', 'set', 'oct', 'nov', 'avi'],
+ 'weekdays' => ['domingo', 'luns', 'martes', 'mierques', 'chueves', 'viernes', 'sabado'],
+ 'weekdays_short' => ['dom', 'lun', 'mar', 'mie', 'chu', 'vie', 'sab'],
+ 'weekdays_min' => ['dom', 'lun', 'mar', 'mie', 'chu', 'vie', 'sab'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'year' => ':count año',
+ 'y' => ':count año',
+ 'a_year' => ':count año',
+
+ 'month' => ':count mes',
+ 'm' => ':count mes',
+ 'a_month' => ':count mes',
+
+ 'week' => ':count semana',
+ 'w' => ':count semana',
+ 'a_week' => ':count semana',
+
+ 'day' => ':count día',
+ 'd' => ':count día',
+ 'a_day' => ':count día',
+
+ 'hour' => ':count reloch', // less reliable
+ 'h' => ':count reloch', // less reliable
+ 'a_hour' => ':count reloch', // less reliable
+
+ 'minute' => ':count minuto',
+ 'min' => ':count minuto',
+ 'a_minute' => ':count minuto',
+
+ 'second' => ':count segundo',
+ 's' => ':count segundo',
+ 'a_second' => ':count segundo',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/anp.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/anp.php
new file mode 100644
index 0000000..b56c67b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/anp.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/anp_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/anp_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/anp_IN.php
new file mode 100644
index 0000000..11069be
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/anp_IN.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bhashaghar@googlegroups.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर"'],
+ 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर'],
+ 'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'बृहस्पतिवार', 'शुक्रवार', 'शनिवार'],
+ 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
+ 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar.php
new file mode 100644
index 0000000..5f73f63
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar.php
@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Atef Ben Ali (atefBB)
+ * - Ibrahim AshShohail
+ * - MLTDev
+ * - Mohamed Sabil (mohamedsabil83)
+ * - Yazan Alnugnugh (yazan-alnugnugh)
+ */
+$months = [
+ 'يناير',
+ 'فبراير',
+ 'مارس',
+ 'أبريل',
+ 'مايو',
+ 'يونيو',
+ 'يوليو',
+ 'أغسطس',
+ 'سبتمبر',
+ 'أكتوبر',
+ 'نوفمبر',
+ 'ديسمبر',
+];
+
+return [
+ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'ago' => 'منذ :time',
+ 'from_now' => ':time من الآن',
+ 'after' => 'بعد :time',
+ 'before' => 'قبل :time',
+ 'diff_now' => 'الآن',
+ 'diff_today' => 'اليوم',
+ 'diff_today_regexp' => 'اليوم(?:\\s+عند)?(?:\\s+الساعة)?',
+ 'diff_yesterday' => 'أمس',
+ 'diff_yesterday_regexp' => 'أمس(?:\\s+عند)?(?:\\s+الساعة)?',
+ 'diff_tomorrow' => 'غداً',
+ 'diff_tomorrow_regexp' => 'غدًا(?:\\s+عند)?(?:\\s+الساعة)?',
+ 'diff_before_yesterday' => 'قبل الأمس',
+ 'diff_after_tomorrow' => 'بعد غد',
+ 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
+ 'period_interval' => 'كل :interval',
+ 'period_start_date' => 'من :date',
+ 'period_end_date' => 'إلى :date',
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
+ 'weekdays_min' => ['ح', 'اث', 'ثل', 'أر', 'خم', 'ج', 'س'],
+ 'list' => ['، ', ' و '],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[اليوم عند الساعة] LT',
+ 'nextDay' => '[غدًا عند الساعة] LT',
+ 'nextWeek' => 'dddd [عند الساعة] LT',
+ 'lastDay' => '[أمس عند الساعة] LT',
+ 'lastWeek' => 'dddd [عند الساعة] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['ص', 'م'],
+ 'weekend' => [5, 6],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_AE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_AE.php
new file mode 100644
index 0000000..75fe47f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_AE.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
+ 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت '],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_BH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_BH.php
new file mode 100644
index 0000000..362009e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_BH.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
+ 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_DJ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_DJ.php
new file mode 100644
index 0000000..8d377ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_DJ.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_DZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_DZ.php
new file mode 100644
index 0000000..aea4eee
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_DZ.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Authors:
+ * - Josh Soref
+ * - Noureddine LOUAHEDJ
+ * - JD Isaacks
+ * - Atef Ben Ali (atefBB)
+ * - Mohamed Sabil (mohamedsabil83)
+ */
+$months = [
+ 'جانفي',
+ 'فيفري',
+ 'مارس',
+ 'أفريل',
+ 'ماي',
+ 'جوان',
+ 'جويلية',
+ 'أوت',
+ 'سبتمبر',
+ 'أكتوبر',
+ 'نوفمبر',
+ 'ديسمبر',
+];
+
+return [
+ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'ago' => 'منذ :time',
+ 'from_now' => 'في :time',
+ 'after' => 'بعد :time',
+ 'before' => 'قبل :time',
+ 'diff_now' => 'الآن',
+ 'diff_today' => 'اليوم',
+ 'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_yesterday' => 'أمس',
+ 'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_tomorrow' => 'غداً',
+ 'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_before_yesterday' => 'قبل الأمس',
+ 'diff_after_tomorrow' => 'بعد غد',
+ 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
+ 'period_interval' => 'كل :interval',
+ 'period_start_date' => 'من :date',
+ 'period_end_date' => 'إلى :date',
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
+ 'weekdays_min' => ['أح', 'إث', 'ثلا', 'أر', 'خم', 'جم', 'سب'],
+ 'list' => ['، ', ' و '],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 4,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[اليوم على الساعة] LT',
+ 'nextDay' => '[غدا على الساعة] LT',
+ 'nextWeek' => 'dddd [على الساعة] LT',
+ 'lastDay' => '[أمس على الساعة] LT',
+ 'lastWeek' => 'dddd [على الساعة] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['ص', 'م'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_EG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_EG.php
new file mode 100644
index 0000000..362009e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_EG.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
+ 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_EH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_EH.php
new file mode 100644
index 0000000..8d377ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_EH.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_ER.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_ER.php
new file mode 100644
index 0000000..8d377ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_ER.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_IL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_IL.php
new file mode 100644
index 0000000..8d377ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_IL.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_IN.php
new file mode 100644
index 0000000..5fecf70
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_IN.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
+ 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_IQ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_IQ.php
new file mode 100644
index 0000000..0ac0995
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_IQ.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
+ 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_JO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_JO.php
new file mode 100644
index 0000000..0ac0995
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_JO.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
+ 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_KM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_KM.php
new file mode 100644
index 0000000..8d377ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_KM.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_KW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_KW.php
new file mode 100644
index 0000000..e6f0531
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_KW.php
@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Authors:
+ * - Josh Soref
+ * - Nusret Parlak
+ * - JD Isaacks
+ * - Atef Ben Ali (atefBB)
+ * - Mohamed Sabil (mohamedsabil83)
+ */
+$months = [
+ 'يناير',
+ 'فبراير',
+ 'مارس',
+ 'أبريل',
+ 'ماي',
+ 'يونيو',
+ 'يوليوز',
+ 'غشت',
+ 'شتنبر',
+ 'أكتوبر',
+ 'نونبر',
+ 'دجنبر',
+];
+
+return [
+ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'ago' => 'منذ :time',
+ 'from_now' => 'في :time',
+ 'after' => 'بعد :time',
+ 'before' => 'قبل :time',
+ 'diff_now' => 'الآن',
+ 'diff_today' => 'اليوم',
+ 'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_yesterday' => 'أمس',
+ 'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_tomorrow' => 'غداً',
+ 'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_before_yesterday' => 'قبل الأمس',
+ 'diff_after_tomorrow' => 'بعد غد',
+ 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
+ 'period_interval' => 'كل :interval',
+ 'period_start_date' => 'من :date',
+ 'period_end_date' => 'إلى :date',
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'list' => ['، ', ' و '],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[اليوم على الساعة] LT',
+ 'nextDay' => '[غدا على الساعة] LT',
+ 'nextWeek' => 'dddd [على الساعة] LT',
+ 'lastDay' => '[أمس على الساعة] LT',
+ 'lastWeek' => 'dddd [على الساعة] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['ص', 'م'],
+ 'weekend' => [5, 6],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_LB.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_LB.php
new file mode 100644
index 0000000..55bb10c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_LB.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
+ 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_LY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_LY.php
new file mode 100644
index 0000000..1f0af49
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_LY.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Atef Ben Ali (atefBB)
+ * - Ibrahim AshShohail
+ * - MLTDev
+ */
+
+$months = [
+ 'يناير',
+ 'فبراير',
+ 'مارس',
+ 'أبريل',
+ 'مايو',
+ 'يونيو',
+ 'يوليو',
+ 'أغسطس',
+ 'سبتمبر',
+ 'أكتوبر',
+ 'نوفمبر',
+ 'ديسمبر',
+];
+
+return [
+ 'year' => implode('|', [':count سنة', 'سنة', 'سنتين', ':count سنوات', ':count سنة']),
+ 'a_year' => implode('|', [':count سنة', 'سنة', 'سنتين', ':count سنوات', ':count سنة']),
+ 'month' => implode('|', [':count شهر', 'شهر', 'شهرين', ':count أشهر', ':count شهر']),
+ 'a_month' => implode('|', [':count شهر', 'شهر', 'شهرين', ':count أشهر', ':count شهر']),
+ 'week' => implode('|', [':count أسبوع', 'أسبوع', 'أسبوعين', ':count أسابيع', ':count أسبوع']),
+ 'a_week' => implode('|', [':count أسبوع', 'أسبوع', 'أسبوعين', ':count أسابيع', ':count أسبوع']),
+ 'day' => implode('|', [':count يوم', 'يوم', 'يومين', ':count أيام', ':count يوم']),
+ 'a_day' => implode('|', [':count يوم', 'يوم', 'يومين', ':count أيام', ':count يوم']),
+ 'hour' => implode('|', [':count ساعة', 'ساعة', 'ساعتين', ':count ساعات', ':count ساعة']),
+ 'a_hour' => implode('|', [':count ساعة', 'ساعة', 'ساعتين', ':count ساعات', ':count ساعة']),
+ 'minute' => implode('|', [':count دقيقة', 'دقيقة', 'دقيقتين', ':count دقائق', ':count دقيقة']),
+ 'a_minute' => implode('|', [':count دقيقة', 'دقيقة', 'دقيقتين', ':count دقائق', ':count دقيقة']),
+ 'second' => implode('|', [':count ثانية', 'ثانية', 'ثانيتين', ':count ثواني', ':count ثانية']),
+ 'a_second' => implode('|', [':count ثانية', 'ثانية', 'ثانيتين', ':count ثواني', ':count ثانية']),
+ 'ago' => 'منذ :time',
+ 'from_now' => ':time من الآن',
+ 'after' => 'بعد :time',
+ 'before' => 'قبل :time',
+ 'diff_now' => 'الآن',
+ 'diff_today' => 'اليوم',
+ 'diff_today_regexp' => 'اليوم(?:\\s+عند)?(?:\\s+الساعة)?',
+ 'diff_yesterday' => 'أمس',
+ 'diff_yesterday_regexp' => 'أمس(?:\\s+عند)?(?:\\s+الساعة)?',
+ 'diff_tomorrow' => 'غداً',
+ 'diff_tomorrow_regexp' => 'غدًا(?:\\s+عند)?(?:\\s+الساعة)?',
+ 'diff_before_yesterday' => 'قبل الأمس',
+ 'diff_after_tomorrow' => 'بعد غد',
+ 'period_recurrences' => implode('|', ['مرة', 'مرة', ':count مرتين', ':count مرات', ':count مرة']),
+ 'period_interval' => 'كل :interval',
+ 'period_start_date' => 'من :date',
+ 'period_end_date' => 'إلى :date',
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
+ 'weekdays_min' => ['ح', 'اث', 'ثل', 'أر', 'خم', 'ج', 'س'],
+ 'list' => ['، ', ' و '],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[اليوم عند الساعة] LT',
+ 'nextDay' => '[غدًا عند الساعة] LT',
+ 'nextWeek' => 'dddd [عند الساعة] LT',
+ 'lastDay' => '[أمس عند الساعة] LT',
+ 'lastWeek' => 'dddd [عند الساعة] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['ص', 'م'],
+ 'weekend' => [5, 6],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_MA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_MA.php
new file mode 100644
index 0000000..047ae05
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_MA.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Authors:
+ * - Josh Soref
+ * - JD Isaacks
+ * - Atef Ben Ali (atefBB)
+ * - Mohamed Sabil (mohamedsabil83)
+ */
+$months = [
+ 'يناير',
+ 'فبراير',
+ 'مارس',
+ 'أبريل',
+ 'ماي',
+ 'يونيو',
+ 'يوليوز',
+ 'غشت',
+ 'شتنبر',
+ 'أكتوبر',
+ 'نونبر',
+ 'دجنبر',
+];
+
+return [
+ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'ago' => 'منذ :time',
+ 'from_now' => 'في :time',
+ 'after' => 'بعد :time',
+ 'before' => 'قبل :time',
+ 'diff_now' => 'الآن',
+ 'diff_today' => 'اليوم',
+ 'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_yesterday' => 'أمس',
+ 'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_tomorrow' => 'غداً',
+ 'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_before_yesterday' => 'قبل الأمس',
+ 'diff_after_tomorrow' => 'بعد غد',
+ 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
+ 'period_interval' => 'كل :interval',
+ 'period_start_date' => 'من :date',
+ 'period_end_date' => 'إلى :date',
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'list' => ['، ', ' و '],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[اليوم على الساعة] LT',
+ 'nextDay' => '[غدا على الساعة] LT',
+ 'nextWeek' => 'dddd [على الساعة] LT',
+ 'lastDay' => '[أمس على الساعة] LT',
+ 'lastWeek' => 'dddd [على الساعة] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['ص', 'م'],
+ 'weekend' => [5, 6],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_MR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_MR.php
new file mode 100644
index 0000000..8d377ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_MR.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_OM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_OM.php
new file mode 100644
index 0000000..362009e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_OM.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
+ 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_PS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_PS.php
new file mode 100644
index 0000000..8d377ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_PS.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_QA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_QA.php
new file mode 100644
index 0000000..362009e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_QA.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
+ 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SA.php
new file mode 100644
index 0000000..10aaa2e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SA.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Authors:
+ * - Josh Soref
+ * - JD Isaacks
+ * - Atef Ben Ali (atefBB)
+ * - Mohamed Sabil (mohamedsabil83)
+ */
+$months = [
+ 'يناير',
+ 'فبراير',
+ 'مارس',
+ 'أبريل',
+ 'مايو',
+ 'يونيو',
+ 'يوليو',
+ 'أغسطس',
+ 'سبتمبر',
+ 'أكتوبر',
+ 'نوفمبر',
+ 'ديسمبر',
+];
+
+return [
+ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'ago' => 'منذ :time',
+ 'from_now' => 'في :time',
+ 'after' => 'بعد :time',
+ 'before' => 'قبل :time',
+ 'diff_now' => 'الآن',
+ 'diff_today' => 'اليوم',
+ 'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_yesterday' => 'أمس',
+ 'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_tomorrow' => 'غداً',
+ 'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_before_yesterday' => 'قبل الأمس',
+ 'diff_after_tomorrow' => 'بعد غد',
+ 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
+ 'period_interval' => 'كل :interval',
+ 'period_start_date' => 'من :date',
+ 'period_end_date' => 'إلى :date',
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'list' => ['، ', ' و '],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[اليوم على الساعة] LT',
+ 'nextDay' => '[غدا على الساعة] LT',
+ 'nextWeek' => 'dddd [على الساعة] LT',
+ 'lastDay' => '[أمس على الساعة] LT',
+ 'lastWeek' => 'dddd [على الساعة] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['ص', 'م'],
+ 'weekend' => [5, 6],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SD.php
new file mode 100644
index 0000000..362009e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SD.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
+ 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SO.php
new file mode 100644
index 0000000..8d377ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SO.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SS.php
new file mode 100644
index 0000000..32f3282
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SS.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
+ 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SY.php
new file mode 100644
index 0000000..0ac0995
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_SY.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
+ 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php
new file mode 100644
index 0000000..c2d4b43
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Abdellah Chadidi
+ * - Atef Ben Ali (atefBB)
+ * - Mohamed Sabil (mohamedsabil83)
+ */
+// Same for long and short
+$months = [
+ // @TODO add shakl to months
+ 'يناير',
+ 'فبراير',
+ 'مارس',
+ 'أبريل',
+ 'مايو',
+ 'يونيو',
+ 'يوليو',
+ 'أغسطس',
+ 'سبتمبر',
+ 'أكتوبر',
+ 'نوفمبر',
+ 'ديسمبر',
+];
+
+return [
+ 'year' => implode('|', ['{0}:count سَنَة', '{1}سَنَة', '{2}سَنَتَيْن', ']2,11[:count سَنَوَات', ']10,Inf[:count سَنَة']),
+ 'a_year' => implode('|', ['{0}:count سَنَة', '{1}سَنَة', '{2}سَنَتَيْن', ']2,11[:count سَنَوَات', ']10,Inf[:count سَنَة']),
+ 'month' => implode('|', ['{0}:count شَهْرَ', '{1}شَهْرَ', '{2}شَهْرَيْن', ']2,11[:count أَشْهُر', ']10,Inf[:count شَهْرَ']),
+ 'a_month' => implode('|', ['{0}:count شَهْرَ', '{1}شَهْرَ', '{2}شَهْرَيْن', ']2,11[:count أَشْهُر', ']10,Inf[:count شَهْرَ']),
+ 'week' => implode('|', ['{0}:count أُسْبُوع', '{1}أُسْبُوع', '{2}أُسْبُوعَيْن', ']2,11[:count أَسَابِيع', ']10,Inf[:count أُسْبُوع']),
+ 'a_week' => implode('|', ['{0}:count أُسْبُوع', '{1}أُسْبُوع', '{2}أُسْبُوعَيْن', ']2,11[:count أَسَابِيع', ']10,Inf[:count أُسْبُوع']),
+ 'day' => implode('|', ['{0}:count يَوْم', '{1}يَوْم', '{2}يَوْمَيْن', ']2,11[:count أَيَّام', ']10,Inf[:count يَوْم']),
+ 'a_day' => implode('|', ['{0}:count يَوْم', '{1}يَوْم', '{2}يَوْمَيْن', ']2,11[:count أَيَّام', ']10,Inf[:count يَوْم']),
+ 'hour' => implode('|', ['{0}:count سَاعَة', '{1}سَاعَة', '{2}سَاعَتَيْن', ']2,11[:count سَاعَات', ']10,Inf[:count سَاعَة']),
+ 'a_hour' => implode('|', ['{0}:count سَاعَة', '{1}سَاعَة', '{2}سَاعَتَيْن', ']2,11[:count سَاعَات', ']10,Inf[:count سَاعَة']),
+ 'minute' => implode('|', ['{0}:count دَقِيقَة', '{1}دَقِيقَة', '{2}دَقِيقَتَيْن', ']2,11[:count دَقَائِق', ']10,Inf[:count دَقِيقَة']),
+ 'a_minute' => implode('|', ['{0}:count دَقِيقَة', '{1}دَقِيقَة', '{2}دَقِيقَتَيْن', ']2,11[:count دَقَائِق', ']10,Inf[:count دَقِيقَة']),
+ 'second' => implode('|', ['{0}:count ثَانِيَة', '{1}ثَانِيَة', '{2}ثَانِيَتَيْن', ']2,11[:count ثَوَان', ']10,Inf[:count ثَانِيَة']),
+ 'a_second' => implode('|', ['{0}:count ثَانِيَة', '{1}ثَانِيَة', '{2}ثَانِيَتَيْن', ']2,11[:count ثَوَان', ']10,Inf[:count ثَانِيَة']),
+ 'ago' => 'مُنْذُ :time',
+ 'from_now' => 'مِنَ الْآن :time',
+ 'after' => 'بَعْدَ :time',
+ 'before' => 'قَبْلَ :time',
+
+ // @TODO add shakl to translations below
+ 'diff_now' => 'الآن',
+ 'diff_today' => 'اليوم',
+ 'diff_today_regexp' => 'اليوم(?:\\s+عند)?(?:\\s+الساعة)?',
+ 'diff_yesterday' => 'أمس',
+ 'diff_yesterday_regexp' => 'أمس(?:\\s+عند)?(?:\\s+الساعة)?',
+ 'diff_tomorrow' => 'غداً',
+ 'diff_tomorrow_regexp' => 'غدًا(?:\\s+عند)?(?:\\s+الساعة)?',
+ 'diff_before_yesterday' => 'قبل الأمس',
+ 'diff_after_tomorrow' => 'بعد غد',
+ 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
+ 'period_interval' => 'كل :interval',
+ 'period_start_date' => 'من :date',
+ 'period_end_date' => 'إلى :date',
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
+ 'weekdays_min' => ['ح', 'اث', 'ثل', 'أر', 'خم', 'ج', 'س'],
+ 'list' => ['، ', ' و '],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[اليوم عند الساعة] LT',
+ 'nextDay' => '[غدًا عند الساعة] LT',
+ 'nextWeek' => 'dddd [عند الساعة] LT',
+ 'lastDay' => '[أمس عند الساعة] LT',
+ 'lastWeek' => 'dddd [عند الساعة] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['ص', 'م'],
+ 'weekend' => [5, 6],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_TD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_TD.php
new file mode 100644
index 0000000..8d377ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_TD.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_TN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_TN.php
new file mode 100644
index 0000000..f096678
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_TN.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Authors:
+ * - JD Isaacks
+ * - Atef Ben Ali (atefBB)
+ * - Mohamed Sabil (mohamedsabil83)
+ */
+$months = [
+ 'جانفي',
+ 'فيفري',
+ 'مارس',
+ 'أفريل',
+ 'ماي',
+ 'جوان',
+ 'جويلية',
+ 'أوت',
+ 'سبتمبر',
+ 'أكتوبر',
+ 'نوفمبر',
+ 'ديسمبر',
+];
+
+return [
+ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
+ 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
+ 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
+ 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
+ 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
+ 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
+ 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
+ 'ago' => 'منذ :time',
+ 'from_now' => 'في :time',
+ 'after' => 'بعد :time',
+ 'before' => 'قبل :time',
+ 'diff_now' => 'الآن',
+ 'diff_today' => 'اليوم',
+ 'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_yesterday' => 'أمس',
+ 'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_tomorrow' => 'غداً',
+ 'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?',
+ 'diff_before_yesterday' => 'قبل الأمس',
+ 'diff_after_tomorrow' => 'بعد غد',
+ 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
+ 'period_interval' => 'كل :interval',
+ 'period_start_date' => 'من :date',
+ 'period_end_date' => 'إلى :date',
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'list' => ['، ', ' و '],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[اليوم على الساعة] LT',
+ 'nextDay' => '[غدا على الساعة] LT',
+ 'nextWeek' => 'dddd [على الساعة] LT',
+ 'lastDay' => '[أمس على الساعة] LT',
+ 'lastWeek' => 'dddd [على الساعة] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['ص', 'م'],
+ 'weekend' => [5, 6],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_YE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_YE.php
new file mode 100644
index 0000000..5dc2938
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ar_YE.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ar.php', [
+ 'formats' => [
+ 'L' => 'DD MMM, YYYY',
+ ],
+ 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
+ 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
+ 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/as.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/as.php
new file mode 100644
index 0000000..04bc3df
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/as.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/as_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/as_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/as_IN.php
new file mode 100644
index 0000000..5fbc3db
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/as_IN.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Amitakhya Phukan, Red Hat bug-glibc@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D-MM-YYYY',
+ ],
+ 'months' => ['জানুৱাৰী', 'ফেব্ৰুৱাৰী', 'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগষ্ট', 'ছেপ্তেম্বৰ', 'অক্টোবৰ', 'নৱেম্বৰ', 'ডিচেম্বৰ'],
+ 'months_short' => ['জানু', 'ফেব্ৰু', 'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগ', 'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'],
+ 'weekdays' => ['দেওবাৰ', 'সোমবাৰ', 'মঙ্গলবাৰ', 'বুধবাৰ', 'বৃহষ্পতিবাৰ', 'শুক্ৰবাৰ', 'শনিবাৰ'],
+ 'weekdays_short' => ['দেও', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি'],
+ 'weekdays_min' => ['দেও', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['পূৰ্ব্বাহ্ন', 'অপৰাহ্ন'],
+
+ 'year' => ':count বছৰ',
+ 'y' => ':count বছৰ',
+ 'a_year' => ':count বছৰ',
+
+ 'month' => ':count মাহ',
+ 'm' => ':count মাহ',
+ 'a_month' => ':count মাহ',
+
+ 'week' => ':count সপ্তাহ',
+ 'w' => ':count সপ্তাহ',
+ 'a_week' => ':count সপ্তাহ',
+
+ 'day' => ':count বাৰ',
+ 'd' => ':count বাৰ',
+ 'a_day' => ':count বাৰ',
+
+ 'hour' => ':count ঘণ্টা',
+ 'h' => ':count ঘণ্টা',
+ 'a_hour' => ':count ঘণ্টা',
+
+ 'minute' => ':count মিনিট',
+ 'min' => ':count মিনিট',
+ 'a_minute' => ':count মিনিট',
+
+ 'second' => ':count দ্বিতীয়',
+ 's' => ':count দ্বিতীয়',
+ 'a_second' => ':count দ্বিতীয়',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/asa.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/asa.php
new file mode 100644
index 0000000..8389757
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/asa.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['icheheavo', 'ichamthi'],
+ 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
+ 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Ijm', 'Jmo'],
+ 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Ijm', 'Jmo'],
+ 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Dec'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ast.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ast.php
new file mode 100644
index 0000000..d9bdebe
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ast.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Jordi Mallach jordi@gnu.org
+ * - Adolfo Jayme-Barrientos (fitojb)
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['de xineru', 'de febreru', 'de marzu', 'd’abril', 'de mayu', 'de xunu', 'de xunetu', 'd’agostu', 'de setiembre', 'd’ochobre', 'de payares', 'd’avientu'],
+ 'months_short' => ['xin', 'feb', 'mar', 'abr', 'may', 'xun', 'xnt', 'ago', 'set', 'och', 'pay', 'avi'],
+ 'weekdays' => ['domingu', 'llunes', 'martes', 'miércoles', 'xueves', 'vienres', 'sábadu'],
+ 'weekdays_short' => ['dom', 'llu', 'mar', 'mié', 'xue', 'vie', 'sáb'],
+ 'weekdays_min' => ['dom', 'llu', 'mar', 'mié', 'xue', 'vie', 'sáb'],
+
+ 'year' => ':count añu|:count años',
+ 'y' => ':count añu|:count años',
+ 'a_year' => 'un añu|:count años',
+
+ 'month' => ':count mes',
+ 'm' => ':count mes',
+ 'a_month' => 'un mes|:count mes',
+
+ 'week' => ':count selmana|:count selmanes',
+ 'w' => ':count selmana|:count selmanes',
+ 'a_week' => 'una selmana|:count selmanes',
+
+ 'day' => ':count día|:count díes',
+ 'd' => ':count día|:count díes',
+ 'a_day' => 'un día|:count díes',
+
+ 'hour' => ':count hora|:count hores',
+ 'h' => ':count hora|:count hores',
+ 'a_hour' => 'una hora|:count hores',
+
+ 'minute' => ':count minutu|:count minutos',
+ 'min' => ':count minutu|:count minutos',
+ 'a_minute' => 'un minutu|:count minutos',
+
+ 'second' => ':count segundu|:count segundos',
+ 's' => ':count segundu|:count segundos',
+ 'a_second' => 'un segundu|:count segundos',
+
+ 'ago' => 'hai :time',
+ 'from_now' => 'en :time',
+ 'after' => ':time dempués',
+ 'before' => ':time enantes',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ast_ES.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ast_ES.php
new file mode 100644
index 0000000..04d7562
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ast_ES.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return require __DIR__.'/ast.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ayc.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ayc.php
new file mode 100644
index 0000000..d6a6f63
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ayc.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ayc_PE.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ayc_PE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ayc_PE.php
new file mode 100644
index 0000000..ff18504
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ayc_PE.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - runasimipi.org libc-alpha@sourceware.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['inïru', 'phiwriru', 'marsu', 'awrila', 'mayu', 'junyu', 'julyu', 'awustu', 'sitimri', 'uktuwri', 'nuwimri', 'risimri'],
+ 'months_short' => ['ini', 'phi', 'mar', 'awr', 'may', 'jun', 'jul', 'awu', 'sit', 'ukt', 'nuw', 'ris'],
+ 'weekdays' => ['tuminku', 'lunisa', 'martisa', 'mirkulisa', 'juywisa', 'wirnisa', 'sawäru'],
+ 'weekdays_short' => ['tum', 'lun', 'mar', 'mir', 'juy', 'wir', 'saw'],
+ 'weekdays_min' => ['tum', 'lun', 'mar', 'mir', 'juy', 'wir', 'saw'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['VM', 'NM'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az.php
new file mode 100644
index 0000000..1e92106
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az.php
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - Kunal Marwaha
+ * - François B
+ * - JD Isaacks
+ * - Orxan
+ * - Şəhriyar İmanov
+ * - Baran Şengül
+ */
+return [
+ 'year' => ':count il',
+ 'a_year' => '{1}bir il|]1,Inf[:count il',
+ 'y' => ':count il',
+ 'month' => ':count ay',
+ 'a_month' => '{1}bir ay|]1,Inf[:count ay',
+ 'm' => ':count ay',
+ 'week' => ':count həftə',
+ 'a_week' => '{1}bir həftə|]1,Inf[:count həftə',
+ 'w' => ':count h.',
+ 'day' => ':count gün',
+ 'a_day' => '{1}bir gün|]1,Inf[:count gün',
+ 'd' => ':count g.',
+ 'hour' => ':count saat',
+ 'a_hour' => '{1}bir saat|]1,Inf[:count saat',
+ 'h' => ':count saat',
+ 'minute' => ':count d.',
+ 'a_minute' => '{1}bir dəqiqə|]1,Inf[:count dəqiqə',
+ 'min' => ':count dəqiqə',
+ 'second' => ':count san.',
+ 'a_second' => '{1}birneçə saniyə|]1,Inf[:count saniyə',
+ 's' => ':count saniyə',
+ 'ago' => ':time əvvəl',
+ 'from_now' => ':time sonra',
+ 'after' => ':time sonra',
+ 'before' => ':time əvvəl',
+ 'diff_now' => 'indi',
+ 'diff_today' => 'bugün',
+ 'diff_today_regexp' => 'bugün(?:\\s+saat)?',
+ 'diff_yesterday' => 'dünən',
+ 'diff_tomorrow' => 'sabah',
+ 'diff_tomorrow_regexp' => 'sabah(?:\\s+saat)?',
+ 'diff_before_yesterday' => 'srağagün',
+ 'diff_after_tomorrow' => 'birisi gün',
+ 'period_recurrences' => ':count dəfədən bir',
+ 'period_interval' => 'hər :interval',
+ 'period_start_date' => ':date tarixindən başlayaraq',
+ 'period_end_date' => ':date tarixinədək',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[bugün saat] LT',
+ 'nextDay' => '[sabah saat] LT',
+ 'nextWeek' => '[gələn həftə] dddd [saat] LT',
+ 'lastDay' => '[dünən] LT',
+ 'lastWeek' => '[keçən həftə] dddd [saat] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ if ($number === 0) { // special case for zero
+ return "$number-ıncı";
+ }
+
+ static $suffixes = [
+ 1 => '-inci',
+ 5 => '-inci',
+ 8 => '-inci',
+ 70 => '-inci',
+ 80 => '-inci',
+ 2 => '-nci',
+ 7 => '-nci',
+ 20 => '-nci',
+ 50 => '-nci',
+ 3 => '-üncü',
+ 4 => '-üncü',
+ 100 => '-üncü',
+ 6 => '-ncı',
+ 9 => '-uncu',
+ 10 => '-uncu',
+ 30 => '-uncu',
+ 60 => '-ıncı',
+ 90 => '-ıncı',
+ ];
+
+ $lastDigit = $number % 10;
+
+ return $number.($suffixes[$lastDigit] ?? $suffixes[$number % 100 - $lastDigit] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
+ },
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'gecə';
+ }
+ if ($hour < 12) {
+ return 'səhər';
+ }
+ if ($hour < 17) {
+ return 'gündüz';
+ }
+
+ return 'axşam';
+ },
+ 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
+ 'months_short' => ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen', 'okt', 'noy', 'dek'],
+ 'months_standalone' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'İyun', 'İyul', 'Avqust', 'Sentyabr', 'Oktyabr', 'Noyabr', 'Dekabr'],
+ 'weekdays' => ['bazar', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
+ 'weekdays_short' => ['baz', 'bze', 'çax', 'çər', 'cax', 'cüm', 'şən'],
+ 'weekdays_min' => ['bz', 'be', 'ça', 'çə', 'ca', 'cü', 'şə'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' və '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_AZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_AZ.php
new file mode 100644
index 0000000..2acf881
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_AZ.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Pablo Saratxaga pablo@mandrakesoft.com
+ */
+return array_replace_recursive(require __DIR__.'/az.php', [
+ 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'],
+ 'weekdays' => ['bazar günü', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
+ 'weekdays_short' => ['baz', 'ber', 'çax', 'çər', 'cax', 'cüm', 'şnb'],
+ 'weekdays_min' => ['baz', 'ber', 'çax', 'çər', 'cax', 'cüm', 'şnb'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_Cyrl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_Cyrl.php
new file mode 100644
index 0000000..d697918
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_Cyrl.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/az.php', [
+ 'weekdays' => ['базар', 'базар ертәси', 'чәршәнбә ахшамы', 'чәршәнбә', 'ҹүмә ахшамы', 'ҹүмә', 'шәнбә'],
+ 'weekdays_short' => ['Б.', 'Б.Е.', 'Ч.А.', 'Ч.', 'Ҹ.А.', 'Ҹ.', 'Ш.'],
+ 'weekdays_min' => ['Б.', 'Б.Е.', 'Ч.А.', 'Ч.', 'Ҹ.А.', 'Ҹ.', 'Ш.'],
+ 'months' => ['јанвар', 'феврал', 'март', 'апрел', 'май', 'ијун', 'ијул', 'август', 'сентјабр', 'октјабр', 'нојабр', 'декабр'],
+ 'months_short' => ['јан', 'фев', 'мар', 'апр', 'май', 'ијн', 'ијл', 'авг', 'сен', 'окт', 'ној', 'дек'],
+ 'months_standalone' => ['Јанвар', 'Феврал', 'Март', 'Апрел', 'Май', 'Ијун', 'Ијул', 'Август', 'Сентјабр', 'Октјабр', 'Нојабр', 'Декабр'],
+ 'meridiem' => ['а', 'п'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_IR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_IR.php
new file mode 100644
index 0000000..991a0ef
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_IR.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Mousa Moradi mousamk@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'OY/OM/OD',
+ ],
+ 'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مئی', 'ژوئن', 'جولای', 'آقۇست', 'سپتامبر', 'اوْکتوْبر', 'نوْوامبر', 'دسامبر'],
+ 'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مئی', 'ژوئن', 'جولای', 'آقۇست', 'سپتامبر', 'اوْکتوْبر', 'نوْوامبر', 'دسامبر'],
+ 'weekdays' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
+ 'weekdays_short' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
+ 'weekdays_min' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
+ 'first_day_of_week' => 6,
+ 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰۴', '۰۵', '۰۶', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱۴', '۱۵', '۱۶', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲۴', '۲۵', '۲۶', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳۴', '۳۵', '۳۶', '۳۷', '۳۸', '۳۹', '۴۰', '۴۱', '۴۲', '۴۳', '۴۴', '۴۵', '۴۶', '۴۷', '۴۸', '۴۹', '۵۰', '۵۱', '۵۲', '۵۳', '۵۴', '۵۵', '۵۶', '۵۷', '۵۸', '۵۹', '۶۰', '۶۱', '۶۲', '۶۳', '۶۴', '۶۵', '۶۶', '۶۷', '۶۸', '۶۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷۴', '۷۵', '۷۶', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸۴', '۸۵', '۸۶', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹۴', '۹۵', '۹۶', '۹۷', '۹۸', '۹۹'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_Latn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_Latn.php
new file mode 100644
index 0000000..8346a5d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/az_Latn.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/az.php', [
+ 'meridiem' => ['a', 'p'],
+ 'weekdays' => ['bazar', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
+ 'weekdays_short' => ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'],
+ 'weekdays_min' => ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'],
+ 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
+ 'months_short' => ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen', 'okt', 'noy', 'dek'],
+ 'months_standalone' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'İyun', 'İyul', 'Avqust', 'Sentyabr', 'Oktyabr', 'Noyabr', 'Dekabr'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'D MMMM YYYY, dddd HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bas.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bas.php
new file mode 100644
index 0000000..1b342bb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bas.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['I bikɛ̂glà', 'I ɓugajɔp'],
+ 'weekdays' => ['ŋgwà nɔ̂y', 'ŋgwà njaŋgumba', 'ŋgwà ûm', 'ŋgwà ŋgê', 'ŋgwà mbɔk', 'ŋgwà kɔɔ', 'ŋgwà jôn'],
+ 'weekdays_short' => ['nɔy', 'nja', 'uum', 'ŋge', 'mbɔ', 'kɔɔ', 'jon'],
+ 'weekdays_min' => ['nɔy', 'nja', 'uum', 'ŋge', 'mbɔ', 'kɔɔ', 'jon'],
+ 'months' => ['Kɔndɔŋ', 'Màcɛ̂l', 'Màtùmb', 'Màtop', 'M̀puyɛ', 'Hìlòndɛ̀', 'Njèbà', 'Hìkaŋ', 'Dìpɔ̀s', 'Bìòôm', 'Màyɛsèp', 'Lìbuy li ńyèe'],
+ 'months_short' => ['kɔn', 'mac', 'mat', 'mto', 'mpu', 'hil', 'nje', 'hik', 'dip', 'bio', 'may', 'liɓ'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+
+ 'second' => ':count móndî', // less reliable
+ 's' => ':count móndî', // less reliable
+ 'a_second' => ':count móndî', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be.php
new file mode 100644
index 0000000..ce8dbe8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be.php
@@ -0,0 +1,168 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+// @codeCoverageIgnoreStart
+if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) {
+ \Symfony\Component\Translation\PluralizationRules::set(function ($number) {
+ return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+ }, 'be');
+}
+// @codeCoverageIgnoreEnd
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - SobakaSlava
+ * - François B
+ * - Serhan Apaydın
+ * - JD Isaacks
+ * - AbadonnaAbbys
+ * - Siomkin Alexander
+ */
+return [
+ 'year' => ':count год|:count гады|:count гадоў',
+ 'a_year' => '{1}год|:count год|:count гады|:count гадоў',
+ 'y' => ':count год|:count гады|:count гадоў',
+ 'month' => ':count месяц|:count месяцы|:count месяцаў',
+ 'a_month' => '{1}месяц|:count месяц|:count месяцы|:count месяцаў',
+ 'm' => ':count месяц|:count месяцы|:count месяцаў',
+ 'week' => ':count тыдзень|:count тыдні|:count тыдняў',
+ 'a_week' => '{1}тыдзень|:count тыдзень|:count тыдні|:count тыдняў',
+ 'w' => ':count тыдзень|:count тыдні|:count тыдняў',
+ 'day' => ':count дзень|:count дні|:count дзён',
+ 'a_day' => '{1}дзень|:count дзень|:count дні|:count дзён',
+ 'd' => ':count дн',
+ 'hour' => ':count гадзіну|:count гадзіны|:count гадзін',
+ 'a_hour' => '{1}гадзіна|:count гадзіна|:count гадзіны|:count гадзін',
+ 'h' => ':count гадзіна|:count гадзіны|:count гадзін',
+ 'minute' => ':count хвіліна|:count хвіліны|:count хвілін',
+ 'a_minute' => '{1}хвіліна|:count хвіліна|:count хвіліны|:count хвілін',
+ 'min' => ':count хв',
+ 'second' => ':count секунда|:count секунды|:count секунд',
+ 'a_second' => '{1}некалькі секунд|:count секунда|:count секунды|:count секунд',
+ 's' => ':count сек',
+
+ 'hour_ago' => ':count гадзіну|:count гадзіны|:count гадзін',
+ 'a_hour_ago' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін',
+ 'h_ago' => ':count гадзіну|:count гадзіны|:count гадзін',
+ 'minute_ago' => ':count хвіліну|:count хвіліны|:count хвілін',
+ 'a_minute_ago' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін',
+ 'min_ago' => ':count хвіліну|:count хвіліны|:count хвілін',
+ 'second_ago' => ':count секунду|:count секунды|:count секунд',
+ 'a_second_ago' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд',
+ 's_ago' => ':count секунду|:count секунды|:count секунд',
+
+ 'hour_from_now' => ':count гадзіну|:count гадзіны|:count гадзін',
+ 'a_hour_from_now' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін',
+ 'h_from_now' => ':count гадзіну|:count гадзіны|:count гадзін',
+ 'minute_from_now' => ':count хвіліну|:count хвіліны|:count хвілін',
+ 'a_minute_from_now' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін',
+ 'min_from_now' => ':count хвіліну|:count хвіліны|:count хвілін',
+ 'second_from_now' => ':count секунду|:count секунды|:count секунд',
+ 'a_second_from_now' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд',
+ 's_from_now' => ':count секунду|:count секунды|:count секунд',
+
+ 'hour_after' => ':count гадзіну|:count гадзіны|:count гадзін',
+ 'a_hour_after' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін',
+ 'h_after' => ':count гадзіну|:count гадзіны|:count гадзін',
+ 'minute_after' => ':count хвіліну|:count хвіліны|:count хвілін',
+ 'a_minute_after' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін',
+ 'min_after' => ':count хвіліну|:count хвіліны|:count хвілін',
+ 'second_after' => ':count секунду|:count секунды|:count секунд',
+ 'a_second_after' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд',
+ 's_after' => ':count секунду|:count секунды|:count секунд',
+
+ 'hour_before' => ':count гадзіну|:count гадзіны|:count гадзін',
+ 'a_hour_before' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін',
+ 'h_before' => ':count гадзіну|:count гадзіны|:count гадзін',
+ 'minute_before' => ':count хвіліну|:count хвіліны|:count хвілін',
+ 'a_minute_before' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін',
+ 'min_before' => ':count хвіліну|:count хвіліны|:count хвілін',
+ 'second_before' => ':count секунду|:count секунды|:count секунд',
+ 'a_second_before' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд',
+ 's_before' => ':count секунду|:count секунды|:count секунд',
+
+ 'ago' => ':time таму',
+ 'from_now' => 'праз :time',
+ 'after' => ':time пасля',
+ 'before' => ':time да',
+ 'diff_now' => 'цяпер',
+ 'diff_today' => 'Сёння',
+ 'diff_today_regexp' => 'Сёння(?:\\s+ў)?',
+ 'diff_yesterday' => 'учора',
+ 'diff_yesterday_regexp' => 'Учора(?:\\s+ў)?',
+ 'diff_tomorrow' => 'заўтра',
+ 'diff_tomorrow_regexp' => 'Заўтра(?:\\s+ў)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY г.',
+ 'LLL' => 'D MMMM YYYY г., HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY г., HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Сёння ў] LT',
+ 'nextDay' => '[Заўтра ў] LT',
+ 'nextWeek' => '[У] dddd [ў] LT',
+ 'lastDay' => '[Учора ў] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $current) {
+ switch ($current->dayOfWeek) {
+ case 1:
+ case 2:
+ case 4:
+ return '[У мінулы] dddd [ў] LT';
+ default:
+ return '[У мінулую] dddd [ў] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ case 'M':
+ case 'd':
+ case 'DDD':
+ case 'w':
+ case 'W':
+ return ($number % 10 === 2 || $number % 10 === 3) && ($number % 100 !== 12 && $number % 100 !== 13) ? $number.'-і' : $number.'-ы';
+ case 'D':
+ return $number.'-га';
+ default:
+ return $number;
+ }
+ },
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'ночы';
+ }
+ if ($hour < 12) {
+ return 'раніцы';
+ }
+ if ($hour < 17) {
+ return 'дня';
+ }
+
+ return 'вечара';
+ },
+ 'months' => ['студзеня', 'лютага', 'сакавіка', 'красавіка', 'траўня', 'чэрвеня', 'ліпеня', 'жніўня', 'верасня', 'кастрычніка', 'лістапада', 'снежня'],
+ 'months_standalone' => ['студзень', 'люты', 'сакавік', 'красавік', 'травень', 'чэрвень', 'ліпень', 'жнівень', 'верасень', 'кастрычнік', 'лістапад', 'снежань'],
+ 'months_short' => ['студ', 'лют', 'сак', 'крас', 'трав', 'чэрв', 'ліп', 'жнів', 'вер', 'каст', 'ліст', 'снеж'],
+ 'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
+ 'weekdays' => ['нядзелю', 'панядзелак', 'аўторак', 'сераду', 'чацвер', 'пятніцу', 'суботу'],
+ 'weekdays_standalone' => ['нядзеля', 'панядзелак', 'аўторак', 'серада', 'чацвер', 'пятніца', 'субота'],
+ 'weekdays_short' => ['нд', 'пн', 'ат', 'ср', 'чц', 'пт', 'сб'],
+ 'weekdays_min' => ['нд', 'пн', 'ат', 'ср', 'чц', 'пт', 'сб'],
+ 'weekdays_regexp' => '/\[ ?[Ууў] ?(?:мінулую|наступную)? ?\] ?dddd/',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' і '],
+ 'months_short_standalone' => ['сту', 'лют', 'сак', 'кра', 'май', 'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be_BY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be_BY.php
new file mode 100644
index 0000000..26684b4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be_BY.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/be.php', [
+ 'months' => ['студзеня', 'лютага', 'сакавіка', 'красавіка', 'мая', 'чэрвеня', 'ліпеня', 'жніўня', 'верасня', 'кастрычніка', 'лістапада', 'снежня'],
+ 'months_short' => ['сту', 'лют', 'сак', 'кра', 'мая', 'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
+ 'weekdays' => ['Нядзеля', 'Панядзелак', 'Аўторак', 'Серада', 'Чацвер', 'Пятніца', 'Субота'],
+ 'weekdays_short' => ['Няд', 'Пан', 'Аўт', 'Срд', 'Чцв', 'Пят', 'Суб'],
+ 'weekdays_min' => ['Няд', 'Пан', 'Аўт', 'Срд', 'Чцв', 'Пят', 'Суб'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be_BY@latin.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be_BY@latin.php
new file mode 100644
index 0000000..517ce83
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be_BY@latin.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['studzienia', 'lutaha', 'sakavika', 'krasavika', 'maja', 'červienia', 'lipienia', 'žniŭnia', 'vieraśnia', 'kastryčnika', 'listapada', 'śniežnia'],
+ 'months_short' => ['Stu', 'Lut', 'Sak', 'Kra', 'Maj', 'Čer', 'Lip', 'Žni', 'Vie', 'Kas', 'Lis', 'Śni'],
+ 'weekdays' => ['Niadziela', 'Paniadziełak', 'Aŭtorak', 'Sierada', 'Čaćvier', 'Piatnica', 'Subota'],
+ 'weekdays_short' => ['Nia', 'Pan', 'Aŭt', 'Sie', 'Čać', 'Pia', 'Sub'],
+ 'weekdays_min' => ['Nia', 'Pan', 'Aŭt', 'Sie', 'Čać', 'Pia', 'Sub'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bem.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bem.php
new file mode 100644
index 0000000..1c3ef03
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bem.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/bem_ZM.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bem_ZM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bem_ZM.php
new file mode 100644
index 0000000..620b579
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bem_ZM.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - ANLoc Martin Benjamin locales@africanlocalization.net
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'MM/DD/YYYY',
+ ],
+ 'months' => ['Januari', 'Februari', 'Machi', 'Epreo', 'Mei', 'Juni', 'Julai', 'Ogasti', 'Septemba', 'Oktoba', 'Novemba', 'Disemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Epr', 'Mei', 'Jun', 'Jul', 'Oga', 'Sep', 'Okt', 'Nov', 'Dis'],
+ 'weekdays' => ['Pa Mulungu', 'Palichimo', 'Palichibuli', 'Palichitatu', 'Palichine', 'Palichisano', 'Pachibelushi'],
+ 'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+ 'weekdays_min' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['uluchelo', 'akasuba'],
+
+ 'year' => 'myaka :count',
+ 'y' => 'myaka :count',
+ 'a_year' => 'myaka :count',
+
+ 'month' => 'myeshi :count',
+ 'm' => 'myeshi :count',
+ 'a_month' => 'myeshi :count',
+
+ 'week' => 'umulungu :count',
+ 'w' => 'umulungu :count',
+ 'a_week' => 'umulungu :count',
+
+ 'day' => 'inshiku :count',
+ 'd' => 'inshiku :count',
+ 'a_day' => 'inshiku :count',
+
+ 'hour' => 'awala :count',
+ 'h' => 'awala :count',
+ 'a_hour' => 'awala :count',
+
+ 'minute' => 'miniti :count',
+ 'min' => 'miniti :count',
+ 'a_minute' => 'miniti :count',
+
+ 'second' => 'sekondi :count',
+ 's' => 'sekondi :count',
+ 'a_second' => 'sekondi :count',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ber.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ber.php
new file mode 100644
index 0000000..685603c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ber.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ber_DZ.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ber_DZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ber_DZ.php
new file mode 100644
index 0000000..38de10a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ber_DZ.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Pablo Saratxaga pablo@mandrakesoft.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
+ 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'],
+ 'weekdays' => ['bazar günü', 'birinci gün', 'ikinci gün', 'üçüncü gün', 'dördüncü gün', 'beşinci gün', 'altıncı gün'],
+ 'weekdays_short' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
+ 'weekdays_min' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ber_MA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ber_MA.php
new file mode 100644
index 0000000..38de10a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ber_MA.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Pablo Saratxaga pablo@mandrakesoft.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
+ 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'],
+ 'weekdays' => ['bazar günü', 'birinci gün', 'ikinci gün', 'üçüncü gün', 'dördüncü gün', 'beşinci gün', 'altıncı gün'],
+ 'weekdays_short' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
+ 'weekdays_min' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bez.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bez.php
new file mode 100644
index 0000000..1facc9d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bez.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['pamilau', 'pamunyi'],
+ 'weekdays' => ['pa mulungu', 'pa shahuviluha', 'pa hivili', 'pa hidatu', 'pa hitayi', 'pa hihanu', 'pa shahulembela'],
+ 'weekdays_short' => ['Mul', 'Vil', 'Hiv', 'Hid', 'Hit', 'Hih', 'Lem'],
+ 'weekdays_min' => ['Mul', 'Vil', 'Hiv', 'Hid', 'Hit', 'Hih', 'Lem'],
+ 'months' => ['pa mwedzi gwa hutala', 'pa mwedzi gwa wuvili', 'pa mwedzi gwa wudatu', 'pa mwedzi gwa wutai', 'pa mwedzi gwa wuhanu', 'pa mwedzi gwa sita', 'pa mwedzi gwa saba', 'pa mwedzi gwa nane', 'pa mwedzi gwa tisa', 'pa mwedzi gwa kumi', 'pa mwedzi gwa kumi na moja', 'pa mwedzi gwa kumi na mbili'],
+ 'months_short' => ['Hut', 'Vil', 'Dat', 'Tai', 'Han', 'Sit', 'Sab', 'Nan', 'Tis', 'Kum', 'Kmj', 'Kmb'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bg.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bg.php
new file mode 100644
index 0000000..0e17673
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bg.php
@@ -0,0 +1,111 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - Serhan Apaydın
+ * - JD Isaacks
+ * - Glavić
+ */
+return [
+ 'year' => ':count година|:count години',
+ 'a_year' => 'година|:count години',
+ 'y' => ':count година|:count години',
+ 'month' => ':count месец|:count месеца',
+ 'a_month' => 'месец|:count месеца',
+ 'm' => ':count месец|:count месеца',
+ 'week' => ':count седмица|:count седмици',
+ 'a_week' => 'седмица|:count седмици',
+ 'w' => ':count седмица|:count седмици',
+ 'day' => ':count ден|:count дни',
+ 'a_day' => 'ден|:count дни',
+ 'd' => ':count ден|:count дни',
+ 'hour' => ':count час|:count часа',
+ 'a_hour' => 'час|:count часа',
+ 'h' => ':count час|:count часа',
+ 'minute' => ':count минута|:count минути',
+ 'a_minute' => 'минута|:count минути',
+ 'min' => ':count минута|:count минути',
+ 'second' => ':count секунда|:count секунди',
+ 'a_second' => 'няколко секунди|:count секунди',
+ 's' => ':count секунда|:count секунди',
+ 'ago' => 'преди :time',
+ 'from_now' => 'след :time',
+ 'after' => 'след :time',
+ 'before' => 'преди :time',
+ 'diff_now' => 'сега',
+ 'diff_today' => 'Днес',
+ 'diff_today_regexp' => 'Днес(?:\\s+в)?',
+ 'diff_yesterday' => 'вчера',
+ 'diff_yesterday_regexp' => 'Вчера(?:\\s+в)?',
+ 'diff_tomorrow' => 'утре',
+ 'diff_tomorrow_regexp' => 'Утре(?:\\s+в)?',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'D.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY H:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Днес в] LT',
+ 'nextDay' => '[Утре в] LT',
+ 'nextWeek' => 'dddd [в] LT',
+ 'lastDay' => '[Вчера в] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $current) {
+ switch ($current->dayOfWeek) {
+ case 0:
+ case 3:
+ case 6:
+ return '[В изминалата] dddd [в] LT';
+ default:
+ return '[В изминалия] dddd [в] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ $lastDigit = $number % 10;
+ $last2Digits = $number % 100;
+ if ($number === 0) {
+ return "$number-ев";
+ }
+ if ($last2Digits === 0) {
+ return "$number-ен";
+ }
+ if ($last2Digits > 10 && $last2Digits < 20) {
+ return "$number-ти";
+ }
+ if ($lastDigit === 1) {
+ return "$number-ви";
+ }
+ if ($lastDigit === 2) {
+ return "$number-ри";
+ }
+ if ($lastDigit === 7 || $lastDigit === 8) {
+ return "$number-ми";
+ }
+
+ return "$number-ти";
+ },
+ 'months' => ['януари', 'февруари', 'март', 'април', 'май', 'юни', 'юли', 'август', 'септември', 'октомври', 'ноември', 'декември'],
+ 'months_short' => ['яну', 'фев', 'мар', 'апр', 'май', 'юни', 'юли', 'авг', 'сеп', 'окт', 'ное', 'дек'],
+ 'weekdays' => ['неделя', 'понеделник', 'вторник', 'сряда', 'четвъртък', 'петък', 'събота'],
+ 'weekdays_short' => ['нед', 'пон', 'вто', 'сря', 'чет', 'пет', 'съб'],
+ 'weekdays_min' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' и '],
+ 'meridiem' => ['преди обяд', 'следобед'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bg_BG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bg_BG.php
new file mode 100644
index 0000000..85c0783
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bg_BG.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/bg.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bhb.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bhb.php
new file mode 100644
index 0000000..49f0803
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bhb.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/bhb_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bhb_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bhb_IN.php
new file mode 100644
index 0000000..ab557cb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bhb_IN.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Samsung Electronics Co., Ltd. alexey.merzlyakov@samsung.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ 'weekdays' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+ 'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+ 'weekdays_min' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bho.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bho.php
new file mode 100644
index 0000000..e9ed0b6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bho.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/bho_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bho_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bho_IN.php
new file mode 100644
index 0000000..bc54f36
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bho_IN.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bhashaghar@googlegroups.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर"'],
+ 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर"'],
+ 'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरुवार', 'शुक्रवार', 'शनिवार'],
+ 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
+ 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
+
+ 'hour' => ':count मौसम',
+ 'h' => ':count मौसम',
+ 'a_hour' => ':count मौसम',
+
+ 'minute' => ':count कला',
+ 'min' => ':count कला',
+ 'a_minute' => ':count कला',
+
+ 'second' => ':count सोमार',
+ 's' => ':count सोमार',
+ 'a_second' => ':count सोमार',
+
+ 'year' => ':count साल',
+ 'y' => ':count साल',
+ 'a_year' => ':count साल',
+
+ 'month' => ':count महिना',
+ 'm' => ':count महिना',
+ 'a_month' => ':count महिना',
+
+ 'week' => ':count सप्ताह',
+ 'w' => ':count सप्ताह',
+ 'a_week' => ':count सप्ताह',
+
+ 'day' => ':count दिन',
+ 'd' => ':count दिन',
+ 'a_day' => ':count दिन',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bi.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bi.php
new file mode 100644
index 0000000..dd08128
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bi.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/bi_VU.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bi_VU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bi_VU.php
new file mode 100644
index 0000000..1fe7770
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bi_VU.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com & maninder1.s@samsung.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'dddd DD MMM YYYY',
+ ],
+ 'months' => ['jenuware', 'febwari', 'maj', 'epril', 'mei', 'jun', 'julae', 'ogis', 'septemba', 'oktoba', 'novemba', 'disemba'],
+ 'months_short' => ['jen', 'feb', 'maj', 'epr', 'mei', 'jun', 'jul', 'ogi', 'sep', 'okt', 'nov', 'dis'],
+ 'weekdays' => ['sande', 'mande', 'maj', 'wota', 'fraede', 'sarede'],
+ 'weekdays_short' => ['san', 'man', 'maj', 'wot', 'fra', 'sar'],
+ 'weekdays_min' => ['san', 'man', 'maj', 'wot', 'fra', 'sar'],
+
+ 'year' => ':count seven', // less reliable
+ 'y' => ':count seven', // less reliable
+ 'a_year' => ':count seven', // less reliable
+
+ 'month' => ':count mi', // less reliable
+ 'm' => ':count mi', // less reliable
+ 'a_month' => ':count mi', // less reliable
+
+ 'week' => ':count sarede', // less reliable
+ 'w' => ':count sarede', // less reliable
+ 'a_week' => ':count sarede', // less reliable
+
+ 'day' => ':count betde', // less reliable
+ 'd' => ':count betde', // less reliable
+ 'a_day' => ':count betde', // less reliable
+
+ 'hour' => ':count klok', // less reliable
+ 'h' => ':count klok', // less reliable
+ 'a_hour' => ':count klok', // less reliable
+
+ 'minute' => ':count smol', // less reliable
+ 'min' => ':count smol', // less reliable
+ 'a_minute' => ':count smol', // less reliable
+
+ 'second' => ':count tu', // less reliable
+ 's' => ':count tu', // less reliable
+ 'a_second' => ':count tu', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bm.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bm.php
new file mode 100644
index 0000000..92822d2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bm.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Estelle Comment
+ */
+return [
+ 'year' => 'san :count',
+ 'a_year' => '{1}san kelen|san :count',
+ 'y' => 'san :count',
+ 'month' => 'kalo :count',
+ 'a_month' => '{1}kalo kelen|kalo :count',
+ 'm' => 'k. :count',
+ 'week' => 'dɔgɔkun :count',
+ 'a_week' => 'dɔgɔkun kelen',
+ 'w' => 'd. :count',
+ 'day' => 'tile :count',
+ 'd' => 't. :count',
+ 'a_day' => '{1}tile kelen|tile :count',
+ 'hour' => 'lɛrɛ :count',
+ 'a_hour' => '{1}lɛrɛ kelen|lɛrɛ :count',
+ 'h' => 'l. :count',
+ 'minute' => 'miniti :count',
+ 'a_minute' => '{1}miniti kelen|miniti :count',
+ 'min' => 'm. :count',
+ 'second' => 'sekondi :count',
+ 'a_second' => '{1}sanga dama dama|sekondi :count',
+ 's' => 'sek. :count',
+ 'ago' => 'a bɛ :time bɔ',
+ 'from_now' => ':time kɔnɔ',
+ 'diff_today' => 'Bi',
+ 'diff_yesterday' => 'Kunu',
+ 'diff_yesterday_regexp' => 'Kunu(?:\\s+lɛrɛ)?',
+ 'diff_tomorrow' => 'Sini',
+ 'diff_tomorrow_regexp' => 'Sini(?:\\s+lɛrɛ)?',
+ 'diff_today_regexp' => 'Bi(?:\\s+lɛrɛ)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'MMMM [tile] D [san] YYYY',
+ 'LLL' => 'MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
+ 'LLLL' => 'dddd MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Bi lɛrɛ] LT',
+ 'nextDay' => '[Sini lɛrɛ] LT',
+ 'nextWeek' => 'dddd [don lɛrɛ] LT',
+ 'lastDay' => '[Kunu lɛrɛ] LT',
+ 'lastWeek' => 'dddd [tɛmɛnen lɛrɛ] LT',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['Zanwuyekalo', 'Fewuruyekalo', 'Marisikalo', 'Awirilikalo', 'Mɛkalo', 'Zuwɛnkalo', 'Zuluyekalo', 'Utikalo', 'Sɛtanburukalo', 'ɔkutɔburukalo', 'Nowanburukalo', 'Desanburukalo'],
+ 'months_short' => ['Zan', 'Few', 'Mar', 'Awi', 'Mɛ', 'Zuw', 'Zul', 'Uti', 'Sɛt', 'ɔku', 'Now', 'Des'],
+ 'weekdays' => ['Kari', 'Ntɛnɛn', 'Tarata', 'Araba', 'Alamisa', 'Juma', 'Sibiri'],
+ 'weekdays_short' => ['Kar', 'Ntɛ', 'Tar', 'Ara', 'Ala', 'Jum', 'Sib'],
+ 'weekdays_min' => ['Ka', 'Nt', 'Ta', 'Ar', 'Al', 'Ju', 'Si'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' ni '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn.php
new file mode 100644
index 0000000..8e14789
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - Shakib Hossain
+ * - Raju
+ * - Aniruddha Adhikary
+ * - JD Isaacks
+ * - Saiful Islam
+ * - Faisal Islam
+ */
+return [
+ 'year' => ':count বছর',
+ 'a_year' => 'এক বছর|:count বছর',
+ 'y' => '১ বছর|:count বছর',
+ 'month' => ':count মাস',
+ 'a_month' => 'এক মাস|:count মাস',
+ 'm' => '১ মাস|:count মাস',
+ 'week' => ':count সপ্তাহ',
+ 'a_week' => '১ সপ্তাহ|:count সপ্তাহ',
+ 'w' => '১ সপ্তাহ|:count সপ্তাহ',
+ 'day' => ':count দিন',
+ 'a_day' => 'এক দিন|:count দিন',
+ 'd' => '১ দিন|:count দিন',
+ 'hour' => ':count ঘন্টা',
+ 'a_hour' => 'এক ঘন্টা|:count ঘন্টা',
+ 'h' => '১ ঘন্টা|:count ঘন্টা',
+ 'minute' => ':count মিনিট',
+ 'a_minute' => 'এক মিনিট|:count মিনিট',
+ 'min' => '১ মিনিট|:count মিনিট',
+ 'second' => ':count সেকেন্ড',
+ 'a_second' => 'কয়েক সেকেন্ড|:count সেকেন্ড',
+ 's' => '১ সেকেন্ড|:count সেকেন্ড',
+ 'ago' => ':time আগে',
+ 'from_now' => ':time পরে',
+ 'after' => ':time পরে',
+ 'before' => ':time আগে',
+ 'diff_now' => 'এখন',
+ 'diff_today' => 'আজ',
+ 'diff_yesterday' => 'গতকাল',
+ 'diff_tomorrow' => 'আগামীকাল',
+ 'period_recurrences' => ':count বার|:count বার',
+ 'period_interval' => 'প্রতি :interval',
+ 'period_start_date' => ':date থেকে',
+ 'period_end_date' => ':date পর্যন্ত',
+ 'formats' => [
+ 'LT' => 'A Oh:Om সময়',
+ 'LTS' => 'A Oh:Om:Os সময়',
+ 'L' => 'OD/OM/OY',
+ 'LL' => 'OD MMMM OY',
+ 'LLL' => 'OD MMMM OY, A Oh:Om সময়',
+ 'LLLL' => 'dddd, OD MMMM OY, A Oh:Om সময়',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[আজ] LT',
+ 'nextDay' => '[আগামীকাল] LT',
+ 'nextWeek' => 'dddd, LT',
+ 'lastDay' => '[গতকাল] LT',
+ 'lastWeek' => '[গত] dddd, LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'রাত';
+ }
+ if ($hour < 10) {
+ return 'সকাল';
+ }
+ if ($hour < 17) {
+ return 'দুপুর';
+ }
+ if ($hour < 20) {
+ return 'বিকাল';
+ }
+
+ return 'রাত';
+ },
+ 'months' => ['জানুয়ারী', 'ফেব্রুয়ারি', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
+ 'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্র', 'মে', 'জুন', 'জুল', 'আগ', 'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'],
+ 'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'],
+ 'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
+ 'weekdays_min' => ['রবি', 'সোম', 'মঙ্গ', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'],
+ 'list' => [', ', ' এবং '],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'weekdays_standalone' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহষ্পতিবার', 'শুক্রবার', 'শনিবার'],
+ 'weekdays_min_standalone' => ['রঃ', 'সোঃ', 'মঃ', 'বুঃ', 'বৃঃ', 'শুঃ', 'শনি'],
+ 'months_short_standalone' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
+ 'alt_numbers' => ['০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn_BD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn_BD.php
new file mode 100644
index 0000000..b5b28dd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn_BD.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ankur Group, Taneem Ahmed, Jamil Ahmed
+ */
+return array_replace_recursive(require __DIR__.'/bn.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
+ 'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
+ 'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'],
+ 'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'],
+ 'weekdays_min' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'],
+ 'first_day_of_week' => 5,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn_IN.php
new file mode 100644
index 0000000..8b3a50e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn_IN.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/bn.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
+ 'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
+ 'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'],
+ 'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
+ 'weekdays_min' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bo.php
new file mode 100644
index 0000000..99e1bf4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bo.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - JD Isaacks
+ */
+return [
+ 'year' => '{1}ལོ་གཅིག|]1,Inf[:count ལོ',
+ 'month' => '{1}ཟླ་བ་གཅིག|]1,Inf[:count ཟླ་བ',
+ 'week' => ':count བདུན་ཕྲག',
+ 'day' => '{1}ཉིན་གཅིག|]1,Inf[:count ཉིན་',
+ 'hour' => '{1}ཆུ་ཚོད་གཅིག|]1,Inf[:count ཆུ་ཚོད',
+ 'minute' => '{1}སྐར་མ་གཅིག|]1,Inf[:count སྐར་མ',
+ 'second' => '{1}ལམ་སང|]1,Inf[:count སྐར་ཆ།',
+ 'ago' => ':time སྔན་ལ',
+ 'from_now' => ':time ལ་',
+ 'diff_yesterday' => 'ཁ་སང',
+ 'diff_today' => 'དི་རིང',
+ 'diff_tomorrow' => 'སང་ཉིན',
+ 'formats' => [
+ 'LT' => 'A h:mm',
+ 'LTS' => 'A h:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, A h:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY, A h:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[དི་རིང] LT',
+ 'nextDay' => '[སང་ཉིན] LT',
+ 'nextWeek' => '[བདུན་ཕྲག་རྗེས་མ], LT',
+ 'lastDay' => '[ཁ་སང] LT',
+ 'lastWeek' => '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'མཚན་མོ';
+ }
+ if ($hour < 10) {
+ return 'ཞོགས་ཀས';
+ }
+ if ($hour < 17) {
+ return 'ཉིན་གུང';
+ }
+ if ($hour < 20) {
+ return 'དགོང་དག';
+ }
+
+ return 'མཚན་མོ';
+ },
+ 'months' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'],
+ 'months_short' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'],
+ 'weekdays' => ['གཟའ་ཉི་མ་', 'གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་', 'གཟའ་ཕུར་བུ', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་པ་'],
+ 'weekdays_short' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ', 'པ་སངས་', 'སྤེན་པ་'],
+ 'weekdays_min' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ', 'པ་སངས་', 'སྤེན་པ་'],
+ 'list' => [', ', ' ཨནད་ '],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'months_standalone' => ['ཟླ་བ་དང་པོ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་པ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུན་པ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bo_CN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bo_CN.php
new file mode 100644
index 0000000..c3d9d8b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bo_CN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/bo.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bo_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bo_IN.php
new file mode 100644
index 0000000..a377fb5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bo_IN.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/bo.php', [
+ 'meridiem' => ['སྔ་དྲོ་', 'ཕྱི་དྲོ་'],
+ 'weekdays' => ['གཟའ་ཉི་མ་', 'གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་', 'གཟའ་ཕུར་བུ་', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་པ་'],
+ 'weekdays_short' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ་', 'པ་སངས་', 'སྤེན་པ་'],
+ 'weekdays_min' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ་', 'པ་སངས་', 'སྤེན་པ་'],
+ 'months' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'],
+ 'months_short' => ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣', 'ཟླ་༤', 'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧', 'ཟླ་༨', 'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡', 'ཟླ་༡༢'],
+ 'months_standalone' => ['ཟླ་བ་དང་པོ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་པ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུན་པ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'],
+ 'weekend' => [0, 0],
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'YYYY ལོའི་MMMཚེས་D',
+ 'LLL' => 'སྤྱི་ལོ་YYYY MMMMའི་ཚེས་D h:mm a',
+ 'LLLL' => 'YYYY MMMMའི་ཚེས་D, dddd h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/br.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/br.php
new file mode 100644
index 0000000..583472f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/br.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Serhan Apaydın
+ * - JD Isaacks
+ */
+return [
+ 'year' => '{1}:count bloaz|{3,4,5,9}:count bloaz|[0,Inf[:count vloaz',
+ 'a_year' => '{1}ur bloaz|{3,4,5,9}:count bloaz|[0,Inf[:count vloaz',
+ 'month' => '{1}:count miz|{2}:count viz|[0,Inf[:count miz',
+ 'a_month' => '{1}ur miz|{2}:count viz|[0,Inf[:count miz',
+ 'week' => ':count sizhun',
+ 'a_week' => '{1}ur sizhun|:count sizhun',
+ 'day' => '{1}:count devezh|{2}:count zevezh|[0,Inf[:count devezh',
+ 'a_day' => '{1}un devezh|{2}:count zevezh|[0,Inf[:count devezh',
+ 'hour' => ':count eur',
+ 'a_hour' => '{1}un eur|:count eur',
+ 'minute' => '{1}:count vunutenn|{2}:count vunutenn|[0,Inf[:count munutenn',
+ 'a_minute' => '{1}ur vunutenn|{2}:count vunutenn|[0,Inf[:count munutenn',
+ 'second' => ':count eilenn',
+ 'a_second' => '{1}un nebeud segondennoù|[0,Inf[:count eilenn',
+ 'ago' => ':time \'zo',
+ 'from_now' => 'a-benn :time',
+ 'diff_now' => 'bremañ',
+ 'diff_today' => 'Hiziv',
+ 'diff_today_regexp' => 'Hiziv(?:\\s+da)?',
+ 'diff_yesterday' => 'decʼh',
+ 'diff_yesterday_regexp' => 'Dec\'h(?:\\s+da)?',
+ 'diff_tomorrow' => 'warcʼhoazh',
+ 'diff_tomorrow_regexp' => 'Warc\'hoazh(?:\\s+da)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D [a viz] MMMM YYYY',
+ 'LLL' => 'D [a viz] MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D [a viz] MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Hiziv da] LT',
+ 'nextDay' => '[Warc\'hoazh da] LT',
+ 'nextWeek' => 'dddd [da] LT',
+ 'lastDay' => '[Dec\'h da] LT',
+ 'lastWeek' => 'dddd [paset da] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ return $number.($number === 1 ? 'añ' : 'vet');
+ },
+ 'months' => ['Genver', 'C\'hwevrer', 'Meurzh', 'Ebrel', 'Mae', 'Mezheven', 'Gouere', 'Eost', 'Gwengolo', 'Here', 'Du', 'Kerzu'],
+ 'months_short' => ['Gen', 'C\'hwe', 'Meu', 'Ebr', 'Mae', 'Eve', 'Gou', 'Eos', 'Gwe', 'Her', 'Du', 'Ker'],
+ 'weekdays' => ['Sul', 'Lun', 'Meurzh', 'Merc\'her', 'Yaou', 'Gwener', 'Sadorn'],
+ 'weekdays_short' => ['Sul', 'Lun', 'Meu', 'Mer', 'Yao', 'Gwe', 'Sad'],
+ 'weekdays_min' => ['Su', 'Lu', 'Me', 'Mer', 'Ya', 'Gw', 'Sa'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' hag '],
+ 'meridiem' => ['A.M.', 'G.M.'],
+
+ 'y' => ':count bl.',
+ 'd' => ':count d',
+ 'h' => ':count e',
+ 'min' => ':count min',
+ 's' => ':count s',
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/br_FR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/br_FR.php
new file mode 100644
index 0000000..9d939fd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/br_FR.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/br.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/brx.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/brx.php
new file mode 100644
index 0000000..a0a7bf9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/brx.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/brx_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/brx_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/brx_IN.php
new file mode 100644
index 0000000..2d80ced
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/brx_IN.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Red Hat Pune bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'M/D/YY',
+ ],
+ 'months' => ['जानुवारी', 'फेब्रुवारी', 'मार्स', 'एफ्रिल', 'मे', 'जुन', 'जुलाइ', 'आगस्थ', 'सेबथेज्ब़र', 'अखथबर', 'नबेज्ब़र', 'दिसेज्ब़र'],
+ 'months_short' => ['जानुवारी', 'फेब्रुवारी', 'मार्स', 'एप्रिल', 'मे', 'जुन', 'जुलाइ', 'आगस्थ', 'सेबथेज्ब़र', 'अखथबर', 'नबेज्ब़र', 'दिसेज्ब़र'],
+ 'weekdays' => ['रबिबार', 'सोबार', 'मंगलबार', 'बुदबार', 'बिसथिबार', 'सुखुरबार', 'सुनिबार'],
+ 'weekdays_short' => ['रबि', 'सम', 'मंगल', 'बुद', 'बिसथि', 'सुखुर', 'सुनि'],
+ 'weekdays_min' => ['रबि', 'सम', 'मंगल', 'बुद', 'बिसथि', 'सुखुर', 'सुनि'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['फुं.', 'बेलासे.'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs.php
new file mode 100644
index 0000000..d2fc5aa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bokideckonja
+ * - Josh Soref
+ * - François B
+ * - shaishavgandhi05
+ * - Serhan Apaydın
+ * - JD Isaacks
+ */
+return [
+ 'year' => ':count godina|:count godine|:count godina',
+ 'y' => ':count godina|:count godine|:count godina',
+ 'month' => ':count mjesec|:count mjeseca|:count mjeseci',
+ 'm' => ':count mjesec|:count mjeseca|:count mjeseci',
+ 'week' => ':count sedmice|:count sedmicu|:count sedmica',
+ 'w' => ':count sedmice|:count sedmicu|:count sedmica',
+ 'day' => ':count dan|:count dana|:count dana',
+ 'd' => ':count dan|:count dana|:count dana',
+ 'hour' => ':count sat|:count sata|:count sati',
+ 'h' => ':count sat|:count sata|:count sati',
+ 'minute' => ':count minut|:count minuta|:count minuta',
+ 'min' => ':count minut|:count minuta|:count minuta',
+ 'second' => ':count sekund|:count sekunda|:count sekundi',
+ 's' => ':count sekund|:count sekunda|:count sekundi',
+ 'ago' => 'prije :time',
+ 'from_now' => 'za :time',
+ 'after' => 'nakon :time',
+ 'before' => ':time ranije',
+ 'diff_now' => 'sada',
+ 'diff_today' => 'danas',
+ 'diff_today_regexp' => 'danas(?:\\s+u)?',
+ 'diff_yesterday' => 'jučer',
+ 'diff_yesterday_regexp' => 'jučer(?:\\s+u)?',
+ 'diff_tomorrow' => 'sutra',
+ 'diff_tomorrow_regexp' => 'sutra(?:\\s+u)?',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY H:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[danas u] LT',
+ 'nextDay' => '[sutra u] LT',
+ 'nextWeek' => function (\Carbon\CarbonInterface $current) {
+ switch ($current->dayOfWeek) {
+ case 0:
+ return '[u] [nedjelju] [u] LT';
+ case 3:
+ return '[u] [srijedu] [u] LT';
+ case 6:
+ return '[u] [subotu] [u] LT';
+ default:
+ return '[u] dddd [u] LT';
+ }
+ },
+ 'lastDay' => '[jučer u] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $current) {
+ switch ($current->dayOfWeek) {
+ case 0:
+ case 3:
+ return '[prošlu] dddd [u] LT';
+ case 6:
+ return '[prošle] [subote] [u] LT';
+ default:
+ return '[prošli] dddd [u] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['januar', 'februar', 'mart', 'april', 'maj', 'juni', 'juli', 'august', 'septembar', 'oktobar', 'novembar', 'decembar'],
+ 'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj.', 'jun.', 'jul.', 'aug.', 'sep.', 'okt.', 'nov.', 'dec.'],
+ 'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
+ 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'],
+ 'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' i '],
+ 'meridiem' => ['prijepodne', 'popodne'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs_BA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs_BA.php
new file mode 100644
index 0000000..4dd21ba
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs_BA.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/bs.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs_Cyrl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs_Cyrl.php
new file mode 100644
index 0000000..09221e0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs_Cyrl.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/bs.php', [
+ 'meridiem' => ['пре подне', 'поподне'],
+ 'weekdays' => ['недјеља', 'понедјељак', 'уторак', 'сриједа', 'четвртак', 'петак', 'субота'],
+ 'weekdays_short' => ['нед', 'пон', 'уто', 'сри', 'чет', 'пет', 'суб'],
+ 'weekdays_min' => ['нед', 'пон', 'уто', 'сри', 'чет', 'пет', 'суб'],
+ 'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јуни', 'јули', 'аугуст', 'септембар', 'октобар', 'новембар', 'децембар'],
+ 'months_short' => ['јан', 'феб', 'мар', 'апр', 'мај', 'јун', 'јул', 'ауг', 'сеп', 'окт', 'нов', 'дец'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D.M.YYYY.',
+ 'LL' => 'DD.MM.YYYY.',
+ 'LLL' => 'DD. MMMM YYYY. HH:mm',
+ 'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs_Latn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs_Latn.php
new file mode 100644
index 0000000..91ed1cc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bs_Latn.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/bs.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/byn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/byn.php
new file mode 100644
index 0000000..7125f3d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/byn.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/byn_ER.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/byn_ER.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/byn_ER.php
new file mode 100644
index 0000000..ad67533
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/byn_ER.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['ልደትሪ', 'ካብኽብቲ', 'ክብላ', 'ፋጅኺሪ', 'ክቢቅሪ', 'ምኪኤል ትጓ̅ኒሪ', 'ኰርኩ', 'ማርያም ትሪ', 'ያኸኒ መሳቅለሪ', 'መተሉ', 'ምኪኤል መሽወሪ', 'ተሕሳስሪ'],
+ 'months_short' => ['ልደት', 'ካብኽ', 'ክብላ', 'ፋጅኺ', 'ክቢቅ', 'ም/ት', 'ኰር', 'ማርያ', 'ያኸኒ', 'መተሉ', 'ም/ም', 'ተሕሳ'],
+ 'weekdays' => ['ሰንበር ቅዳዅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ ወሪ ለብዋ', 'ኣምድ', 'ኣርብ', 'ሰንበር ሽጓዅ'],
+ 'weekdays_short' => ['ሰ/ቅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ', 'ኣምድ', 'ኣርብ', 'ሰ/ሽ'],
+ 'weekdays_min' => ['ሰ/ቅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ', 'ኣምድ', 'ኣርብ', 'ሰ/ሽ'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ፋዱስ ጃብ', 'ፋዱስ ደምቢ'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca.php
new file mode 100644
index 0000000..5c91439
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - mestremuten
+ * - François B
+ * - Marc Ordinas i Llopis
+ * - Pere Orga
+ * - JD Isaacks
+ * - Quentí
+ * - Víctor Díaz
+ * - Xavi
+ * - qcardona
+ */
+return [
+ 'year' => ':count any|:count anys',
+ 'a_year' => 'un any|:count anys',
+ 'y' => ':count any|:count anys',
+ 'month' => ':count mes|:count mesos',
+ 'a_month' => 'un mes|:count mesos',
+ 'm' => ':count mes|:count mesos',
+ 'week' => ':count setmana|:count setmanes',
+ 'a_week' => 'una setmana|:count setmanes',
+ 'w' => ':count setmana|:count setmanes',
+ 'day' => ':count dia|:count dies',
+ 'a_day' => 'un dia|:count dies',
+ 'd' => ':count d',
+ 'hour' => ':count hora|:count hores',
+ 'a_hour' => 'una hora|:count hores',
+ 'h' => ':count h',
+ 'minute' => ':count minut|:count minuts',
+ 'a_minute' => 'un minut|:count minuts',
+ 'min' => ':count min',
+ 'second' => ':count segon|:count segons',
+ 'a_second' => 'uns segons|:count segons',
+ 's' => ':count s',
+ 'ago' => 'fa :time',
+ 'from_now' => 'd\'aquí a :time',
+ 'after' => ':time després',
+ 'before' => ':time abans',
+ 'diff_now' => 'ara mateix',
+ 'diff_today' => 'avui',
+ 'diff_today_regexp' => 'avui(?:\\s+a)?(?:\\s+les)?',
+ 'diff_yesterday' => 'ahir',
+ 'diff_yesterday_regexp' => 'ahir(?:\\s+a)?(?:\\s+les)?',
+ 'diff_tomorrow' => 'demà',
+ 'diff_tomorrow_regexp' => 'demà(?:\\s+a)?(?:\\s+les)?',
+ 'diff_before_yesterday' => 'abans d\'ahir',
+ 'diff_after_tomorrow' => 'demà passat',
+ 'period_recurrences' => ':count cop|:count cops',
+ 'period_interval' => 'cada :interval',
+ 'period_start_date' => 'de :date',
+ 'period_end_date' => 'fins a :date',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM [de] YYYY',
+ 'LLL' => 'D MMMM [de] YYYY [a les] H:mm',
+ 'LLLL' => 'dddd D MMMM [de] YYYY [a les] H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => function (\Carbon\CarbonInterface $current) {
+ return '[avui a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
+ },
+ 'nextDay' => function (\Carbon\CarbonInterface $current) {
+ return '[demà a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
+ },
+ 'nextWeek' => function (\Carbon\CarbonInterface $current) {
+ return 'dddd [a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
+ },
+ 'lastDay' => function (\Carbon\CarbonInterface $current) {
+ return '[ahir a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
+ },
+ 'lastWeek' => function (\Carbon\CarbonInterface $current) {
+ return '[el] dddd [passat a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ return $number.(
+ ($period === 'w' || $period === 'W') ? 'a' : (
+ ($number === 1) ? 'r' : (
+ ($number === 2) ? 'n' : (
+ ($number === 3) ? 'r' : (
+ ($number === 4) ? 't' : 'è'
+ )
+ )
+ )
+ )
+ );
+ },
+ 'months' => ['de gener', 'de febrer', 'de març', 'd\'abril', 'de maig', 'de juny', 'de juliol', 'd\'agost', 'de setembre', 'd\'octubre', 'de novembre', 'de desembre'],
+ 'months_standalone' => ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
+ 'months_short' => ['de gen.', 'de febr.', 'de març', 'd\'abr.', 'de maig', 'de juny', 'de jul.', 'd\'ag.', 'de set.', 'd\'oct.', 'de nov.', 'de des.'],
+ 'months_short_standalone' => ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'],
+ 'months_regexp' => '/(D[oD]?[\s,]+MMMM?|L{2,4}|l{2,4})/',
+ 'weekdays' => ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous', 'divendres', 'dissabte'],
+ 'weekdays_short' => ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
+ 'weekdays_min' => ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' i '],
+ 'meridiem' => ['a. m.', 'p. m.'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_AD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_AD.php
new file mode 100644
index 0000000..f5718c3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_AD.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ca.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_ES.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_ES.php
new file mode 100644
index 0000000..8423606
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_ES.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ca.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_ES_Valencia.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_ES_Valencia.php
new file mode 100644
index 0000000..f5718c3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_ES_Valencia.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ca.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_FR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_FR.php
new file mode 100644
index 0000000..f5718c3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_FR.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ca.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_IT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_IT.php
new file mode 100644
index 0000000..f5718c3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ca_IT.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ca.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ccp.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ccp.php
new file mode 100644
index 0000000..ec616a7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ccp.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'weekdays' => ['𑄢𑄧𑄝𑄨𑄝𑄢𑄴', '𑄥𑄧𑄟𑄴𑄝𑄢𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴𑄝𑄢𑄴', '𑄝𑄪𑄖𑄴𑄝𑄢𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴𑄝𑄢𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴𑄝𑄢𑄴', '𑄥𑄧𑄚𑄨𑄝𑄢𑄴'],
+ 'weekdays_short' => ['𑄢𑄧𑄝𑄨', '𑄥𑄧𑄟𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴', '𑄝𑄪𑄖𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴', '𑄥𑄧𑄚𑄨'],
+ 'weekdays_min' => ['𑄢𑄧𑄝𑄨', '𑄥𑄧𑄟𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴', '𑄝𑄪𑄖𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴', '𑄥𑄧𑄚𑄨'],
+ 'months' => ['𑄎𑄚𑄪𑄠𑄢𑄨', '𑄜𑄬𑄛𑄴𑄝𑄳𑄢𑄪𑄠𑄢𑄨', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄬𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄧𑄢𑄴'],
+ 'months_short' => ['𑄎𑄚𑄪', '𑄜𑄬𑄛𑄴', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄮𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄢𑄴'],
+ 'months_short_standalone' => ['𑄎𑄚𑄪𑄠𑄢𑄨', '𑄜𑄬𑄛𑄴𑄝𑄳𑄢𑄪𑄠𑄢𑄨', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄮𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄧𑄢𑄴'],
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM, YYYY h:mm a',
+ 'LLLL' => 'dddd, D MMMM, YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ccp_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ccp_IN.php
new file mode 100644
index 0000000..18bd122
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ccp_IN.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ccp.php', [
+ 'weekend' => [0, 0],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ce.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ce.php
new file mode 100644
index 0000000..f99f6ff
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ce.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ce_RU.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ce_RU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ce_RU.php
new file mode 100644
index 0000000..f769856
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ce_RU.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - ANCHR
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY.DD.MM',
+ ],
+ 'months' => ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
+ 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
+ 'weekdays' => ['КӀиранан де', 'Оршотан де', 'Шинарин де', 'Кхаарин де', 'Еарин де', 'ПӀераскан де', 'Шот де'],
+ 'weekdays_short' => ['КӀ', 'Ор', 'Ши', 'Кх', 'Еа', 'ПӀ', 'Шо'],
+ 'weekdays_min' => ['КӀ', 'Ор', 'Ши', 'Кх', 'Еа', 'ПӀ', 'Шо'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count шо',
+ 'y' => ':count шо',
+ 'a_year' => ':count шо',
+
+ 'month' => ':count бутт',
+ 'm' => ':count бутт',
+ 'a_month' => ':count бутт',
+
+ 'week' => ':count кӏира',
+ 'w' => ':count кӏира',
+ 'a_week' => ':count кӏира',
+
+ 'day' => ':count де',
+ 'd' => ':count де',
+ 'a_day' => ':count де',
+
+ 'hour' => ':count сахьт',
+ 'h' => ':count сахьт',
+ 'a_hour' => ':count сахьт',
+
+ 'minute' => ':count минот',
+ 'min' => ':count минот',
+ 'a_minute' => ':count минот',
+
+ 'second' => ':count секунд',
+ 's' => ':count секунд',
+ 'a_second' => ':count секунд',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cgg.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cgg.php
new file mode 100644
index 0000000..e424408
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cgg.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'weekdays' => ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu', 'Orwakana', 'Orwakataano', 'Orwamukaaga'],
+ 'weekdays_short' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
+ 'weekdays_min' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
+ 'months' => ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana', 'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda', 'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'],
+ 'months_short' => ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS', 'KMN', 'KMW', 'KKM', 'KNK', 'KNB'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+
+ 'day' => ':count ruhanga', // less reliable
+ 'd' => ':count ruhanga', // less reliable
+ 'a_day' => ':count ruhanga', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/chr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/chr.php
new file mode 100644
index 0000000..e26190f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/chr.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/chr_US.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/chr_US.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/chr_US.php
new file mode 100644
index 0000000..371353e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/chr_US.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Cherokee Nation Joseph Erb josepherb7@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'MM/DD/YYYY',
+ ],
+ 'months' => ['ᎤᏃᎸᏔᏅ', 'ᎧᎦᎵ', 'ᎠᏅᏱ', 'ᎧᏬᏂ', 'ᎠᏂᏍᎬᏘ', 'ᏕᎭᎷᏱ', 'ᎫᏰᏉᏂ', 'ᎦᎶᏂ', 'ᏚᎵᏍᏗ', 'ᏚᏂᏅᏗ', 'ᏅᏓᏕᏆ', 'ᎥᏍᎩᏱ'],
+ 'months_short' => ['ᎤᏃ', 'ᎧᎦ', 'ᎠᏅ', 'ᎧᏬ', 'ᎠᏂ', 'ᏕᎭ', 'ᎫᏰ', 'ᎦᎶ', 'ᏚᎵ', 'ᏚᏂ', 'ᏅᏓ', 'ᎥᏍ'],
+ 'weekdays' => ['ᎤᎾᏙᏓᏆᏍᎬ', 'ᎤᎾᏙᏓᏉᏅᎯ', 'ᏔᎵᏁᎢᎦ', 'ᏦᎢᏁᎢᎦ', 'ᏅᎩᏁᎢᎦ', 'ᏧᎾᎩᎶᏍᏗ', 'ᎤᎾᏙᏓᏈᏕᎾ'],
+ 'weekdays_short' => ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ', 'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'],
+ 'weekdays_min' => ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ', 'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ᏌᎾᎴ', 'ᏒᎯᏱᎢᏗᏢ', 'ꮜꮎꮄ', 'ꮢꭿᏹꭲꮧꮲ'],
+
+ 'second' => ':count ᏐᎢ', // less reliable
+ 's' => ':count ᏐᎢ', // less reliable
+ 'a_second' => ':count ᏐᎢ', // less reliable
+
+ 'year' => ':count ᏑᏕᏘᏴᏓ',
+ 'y' => ':count ᏑᏕᏘᏴᏓ',
+ 'a_year' => ':count ᏑᏕᏘᏴᏓ',
+
+ 'month' => ':count ᏏᏅᏙ',
+ 'm' => ':count ᏏᏅᏙ',
+ 'a_month' => ':count ᏏᏅᏙ',
+
+ 'week' => ':count ᏑᎾᏙᏓᏆᏍᏗ',
+ 'w' => ':count ᏑᎾᏙᏓᏆᏍᏗ',
+ 'a_week' => ':count ᏑᎾᏙᏓᏆᏍᏗ',
+
+ 'day' => ':count ᎢᎦ',
+ 'd' => ':count ᎢᎦ',
+ 'a_day' => ':count ᎢᎦ',
+
+ 'hour' => ':count ᏑᏟᎶᏛ',
+ 'h' => ':count ᏑᏟᎶᏛ',
+ 'a_hour' => ':count ᏑᏟᎶᏛ',
+
+ 'minute' => ':count ᎢᏯᏔᏬᏍᏔᏅ',
+ 'min' => ':count ᎢᏯᏔᏬᏍᏔᏅ',
+ 'a_minute' => ':count ᎢᏯᏔᏬᏍᏔᏅ',
+
+ 'ago' => ':time ᏥᎨᏒ',
+ 'from_now' => 'ᎾᎿ :time',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cmn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cmn.php
new file mode 100644
index 0000000..80b1d69
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cmn.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/cmn_TW.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cmn_TW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cmn_TW.php
new file mode 100644
index 0000000..7e43f9d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cmn_TW.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY年MM月DD號',
+ ],
+ 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ 'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'],
+ 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
+ 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'meridiem' => ['上午', '下午'],
+
+ 'year' => ':count 年',
+ 'y' => ':count 年',
+ 'a_year' => ':count 年',
+
+ 'month' => ':count 月',
+ 'm' => ':count 月',
+ 'a_month' => ':count 月',
+
+ 'week' => ':count 周',
+ 'w' => ':count 周',
+ 'a_week' => ':count 周',
+
+ 'day' => ':count 白天',
+ 'd' => ':count 白天',
+ 'a_day' => ':count 白天',
+
+ 'hour' => ':count 小时',
+ 'h' => ':count 小时',
+ 'a_hour' => ':count 小时',
+
+ 'minute' => ':count 分钟',
+ 'min' => ':count 分钟',
+ 'a_minute' => ':count 分钟',
+
+ 'second' => ':count 秒',
+ 's' => ':count 秒',
+ 'a_second' => ':count 秒',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/crh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/crh.php
new file mode 100644
index 0000000..a1d7ce6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/crh.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/crh_UA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/crh_UA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/crh_UA.php
new file mode 100644
index 0000000..0513933
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/crh_UA.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Reşat SABIQ tilde.birlik@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'Mayıs', 'İyun', 'İyul', 'Avgust', 'Sentâbr', 'Oktâbr', 'Noyabr', 'Dekabr'],
+ 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'],
+ 'weekdays' => ['Bazar', 'Bazarertesi', 'Salı', 'Çarşembe', 'Cumaaqşamı', 'Cuma', 'Cumaertesi'],
+ 'weekdays_short' => ['Baz', 'Ber', 'Sal', 'Çar', 'Caq', 'Cum', 'Cer'],
+ 'weekdays_min' => ['Baz', 'Ber', 'Sal', 'Çar', 'Caq', 'Cum', 'Cer'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ÜE', 'ÜS'],
+
+ 'year' => ':count yıl',
+ 'y' => ':count yıl',
+ 'a_year' => ':count yıl',
+
+ 'month' => ':count ay',
+ 'm' => ':count ay',
+ 'a_month' => ':count ay',
+
+ 'week' => ':count afta',
+ 'w' => ':count afta',
+ 'a_week' => ':count afta',
+
+ 'day' => ':count kün',
+ 'd' => ':count kün',
+ 'a_day' => ':count kün',
+
+ 'hour' => ':count saat',
+ 'h' => ':count saat',
+ 'a_hour' => ':count saat',
+
+ 'minute' => ':count daqqa',
+ 'min' => ':count daqqa',
+ 'a_minute' => ':count daqqa',
+
+ 'second' => ':count ekinci',
+ 's' => ':count ekinci',
+ 'a_second' => ':count ekinci',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cs.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cs.php
new file mode 100644
index 0000000..8cff9a0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cs.php
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - Jakub Tesinsky
+ * - Martin Suja
+ * - Nikos Timiopulos
+ * - Bohuslav Blín
+ * - Tsutomu Kuroda
+ * - tjku
+ * - Lukas Svoboda
+ * - Max Melentiev
+ * - Juanito Fatas
+ * - Akira Matsuda
+ * - Christopher Dell
+ * - Václav Pávek
+ * - CodeSkills
+ * - Tlapi
+ * - newman101
+ * - Petr Kadlec
+ * - tommaskraus
+ * - Karel Sommer (calvera)
+ */
+$za = function ($time) {
+ return 'za '.strtr($time, [
+ 'hodina' => 'hodinu',
+ 'minuta' => 'minutu',
+ 'sekunda' => 'sekundu',
+ ]);
+};
+
+$pred = function ($time) {
+ $time = strtr($time, [
+ 'hodina' => 'hodinou',
+ 'minuta' => 'minutou',
+ 'sekunda' => 'sekundou',
+ ]);
+ $time = preg_replace('/hodiny?(?!\w)/', 'hodinami', $time);
+ $time = preg_replace('/minuty?(?!\w)/', 'minutami', $time);
+ $time = preg_replace('/sekundy?(?!\w)/', 'sekundami', $time);
+
+ return "před $time";
+};
+
+return [
+ 'year' => ':count rok|:count roky|:count let',
+ 'y' => ':count rok|:count roky|:count let',
+ 'a_year' => 'rok|:count roky|:count let',
+ 'month' => ':count měsíc|:count měsíce|:count měsíců',
+ 'm' => ':count měs.',
+ 'a_month' => 'měsíc|:count měsíce|:count měsíců',
+ 'week' => ':count týden|:count týdny|:count týdnů',
+ 'w' => ':count týd.',
+ 'a_week' => 'týden|:count týdny|:count týdnů',
+ 'day' => ':count den|:count dny|:count dní',
+ 'd' => ':count den|:count dny|:count dní',
+ 'a_day' => 'den|:count dny|:count dní',
+ 'hour' => ':count hodina|:count hodiny|:count hodin',
+ 'h' => ':count hod.',
+ 'a_hour' => 'hodina|:count hodiny|:count hodin',
+ 'minute' => ':count minuta|:count minuty|:count minut',
+ 'min' => ':count min.',
+ 'a_minute' => 'minuta|:count minuty|:count minut',
+ 'second' => ':count sekunda|:count sekundy|:count sekund',
+ 's' => ':count sek.',
+ 'a_second' => 'pár sekund|:count sekundy|:count sekund',
+
+ 'month_ago' => ':count měsícem|:count měsíci|:count měsíci',
+ 'a_month_ago' => 'měsícem|:count měsíci|:count měsíci',
+ 'day_ago' => ':count dnem|:count dny|:count dny',
+ 'a_day_ago' => 'dnem|:count dny|:count dny',
+ 'week_ago' => ':count týdnem|:count týdny|:count týdny',
+ 'a_week_ago' => 'týdnem|:count týdny|:count týdny',
+ 'year_ago' => ':count rokem|:count roky|:count lety',
+ 'y_ago' => ':count rok.|:count rok.|:count let.',
+ 'a_year_ago' => 'rokem|:count roky|:count lety',
+
+ 'month_before' => ':count měsícem|:count měsíci|:count měsíci',
+ 'a_month_before' => 'měsícem|:count měsíci|:count měsíci',
+ 'day_before' => ':count dnem|:count dny|:count dny',
+ 'a_day_before' => 'dnem|:count dny|:count dny',
+ 'week_before' => ':count týdnem|:count týdny|:count týdny',
+ 'a_week_before' => 'týdnem|:count týdny|:count týdny',
+ 'year_before' => ':count rokem|:count roky|:count lety',
+ 'y_before' => ':count rok.|:count rok.|:count let.',
+ 'a_year_before' => 'rokem|:count roky|:count lety',
+
+ 'ago' => $pred,
+ 'from_now' => $za,
+ 'before' => $pred,
+ 'after' => $za,
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'months' => ['leden', 'únor', 'březen', 'duben', 'květen', 'červen', 'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec'],
+ 'months_short' => ['led', 'úno', 'bře', 'dub', 'kvě', 'čvn', 'čvc', 'srp', 'zář', 'říj', 'lis', 'pro'],
+ 'weekdays' => ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],
+ 'weekdays_short' => ['ned', 'pon', 'úte', 'stř', 'čtv', 'pát', 'sob'],
+ 'weekdays_min' => ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
+ 'list' => [', ', ' a '],
+ 'diff_now' => 'nyní',
+ 'diff_yesterday' => 'včera',
+ 'diff_tomorrow' => 'zítra',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD. MM. YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D. MMMM YYYY HH:mm',
+ ],
+ 'meridiem' => ['dopoledne', 'odpoledne'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cs_CZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cs_CZ.php
new file mode 100644
index 0000000..a16a346
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cs_CZ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/cs.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/csb.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/csb.php
new file mode 100644
index 0000000..a35d281
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/csb.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/csb_PL.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/csb_PL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/csb_PL.php
new file mode 100644
index 0000000..25e0ca8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/csb_PL.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - csb_PL locale Michal Ostrowski bug-glibc-locales@gnu.org
+ */
+return [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'MMMM DD, YYYY',
+ 'LLL' => 'DD MMM HH:mm',
+ 'LLLL' => 'MMMM DD, YYYY HH:mm',
+ ],
+ 'months' => ['stëcznika', 'gromicznika', 'strëmiannika', 'łżëkwiata', 'maja', 'czerwińca', 'lëpińca', 'zélnika', 'séwnika', 'rujana', 'lëstopadnika', 'gòdnika'],
+ 'months_short' => ['stë', 'gro', 'str', 'łżë', 'maj', 'cze', 'lëp', 'zél', 'séw', 'ruj', 'lës', 'gòd'],
+ 'weekdays' => ['niedzela', 'pòniedzôłk', 'wtórk', 'strzoda', 'czwiôrtk', 'piątk', 'sobòta'],
+ 'weekdays_short' => ['nie', 'pòn', 'wtó', 'str', 'czw', 'pią', 'sob'],
+ 'weekdays_min' => ['nie', 'pòn', 'wtó', 'str', 'czw', 'pią', 'sob'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' a téż '],
+ 'two_words_connector' => ' a téż ',
+ 'year' => ':count rok',
+ 'month' => ':count miesiąc',
+ 'week' => ':count tidzéń',
+ 'day' => ':count dzéń',
+ 'hour' => ':count gòdzëna',
+ 'minute' => ':count minuta',
+ 'second' => ':count sekunda',
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cu.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cu.php
new file mode 100644
index 0000000..02c983a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cu.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
+ 'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'YYYY MMMM D HH:mm',
+ 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
+ ],
+
+ 'year' => ':count лѣто',
+ 'y' => ':count лѣто',
+ 'a_year' => ':count лѣто',
+
+ 'month' => ':count мѣсѧць',
+ 'm' => ':count мѣсѧць',
+ 'a_month' => ':count мѣсѧць',
+
+ 'week' => ':count сєдмица',
+ 'w' => ':count сєдмица',
+ 'a_week' => ':count сєдмица',
+
+ 'day' => ':count дьнь',
+ 'd' => ':count дьнь',
+ 'a_day' => ':count дьнь',
+
+ 'hour' => ':count година',
+ 'h' => ':count година',
+ 'a_hour' => ':count година',
+
+ 'minute' => ':count малъ', // less reliable
+ 'min' => ':count малъ', // less reliable
+ 'a_minute' => ':count малъ', // less reliable
+
+ 'second' => ':count въторъ',
+ 's' => ':count въторъ',
+ 'a_second' => ':count въторъ',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cv.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cv.php
new file mode 100644
index 0000000..cec1fc9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cv.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - JD Isaacks
+ */
+return [
+ 'year' => ':count ҫул',
+ 'a_year' => '{1}пӗр ҫул|:count ҫул',
+ 'month' => ':count уйӑх',
+ 'a_month' => '{1}пӗр уйӑх|:count уйӑх',
+ 'week' => ':count эрне',
+ 'a_week' => '{1}пӗр эрне|:count эрне',
+ 'day' => ':count кун',
+ 'a_day' => '{1}пӗр кун|:count кун',
+ 'hour' => ':count сехет',
+ 'a_hour' => '{1}пӗр сехет|:count сехет',
+ 'minute' => ':count минут',
+ 'a_minute' => '{1}пӗр минут|:count минут',
+ 'second' => ':count ҫеккунт',
+ 'a_second' => '{1}пӗр-ик ҫеккунт|:count ҫеккунт',
+ 'ago' => ':time каялла',
+ 'from_now' => function ($time) {
+ return $time.(preg_match('/сехет$/', $time) ? 'рен' : (preg_match('/ҫул/', $time) ? 'тан' : 'ран'));
+ },
+ 'diff_yesterday' => 'Ӗнер',
+ 'diff_today' => 'Паян',
+ 'diff_tomorrow' => 'Ыран',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD-MM-YYYY',
+ 'LL' => 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]',
+ 'LLL' => 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
+ 'LLLL' => 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Паян] LT [сехетре]',
+ 'nextDay' => '[Ыран] LT [сехетре]',
+ 'nextWeek' => '[Ҫитес] dddd LT [сехетре]',
+ 'lastDay' => '[Ӗнер] LT [сехетре]',
+ 'lastWeek' => '[Иртнӗ] dddd LT [сехетре]',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number-мӗш',
+ 'months' => ['кӑрлач', 'нарӑс', 'пуш', 'ака', 'май', 'ҫӗртме', 'утӑ', 'ҫурла', 'авӑн', 'юпа', 'чӳк', 'раштав'],
+ 'months_short' => ['кӑр', 'нар', 'пуш', 'ака', 'май', 'ҫӗр', 'утӑ', 'ҫур', 'авн', 'юпа', 'чӳк', 'раш'],
+ 'weekdays' => ['вырсарникун', 'тунтикун', 'ытларикун', 'юнкун', 'кӗҫнерникун', 'эрнекун', 'шӑматкун'],
+ 'weekdays_short' => ['выр', 'тун', 'ытл', 'юн', 'кӗҫ', 'эрн', 'шӑм'],
+ 'weekdays_min' => ['вр', 'тн', 'ыт', 'юн', 'кҫ', 'эр', 'шм'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' тата '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cv_RU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cv_RU.php
new file mode 100644
index 0000000..ddff893
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cv_RU.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/cv.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cy.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cy.php
new file mode 100644
index 0000000..ab7c45a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cy.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - JD Isaacks
+ * - Daniel Monaghan
+ */
+return [
+ 'year' => '{1}blwyddyn|]1,Inf[:count flynedd',
+ 'y' => ':countbl',
+ 'month' => '{1}mis|]1,Inf[:count mis',
+ 'm' => ':countmi',
+ 'week' => ':count wythnos',
+ 'w' => ':countw',
+ 'day' => '{1}diwrnod|]1,Inf[:count diwrnod',
+ 'd' => ':countd',
+ 'hour' => '{1}awr|]1,Inf[:count awr',
+ 'h' => ':counth',
+ 'minute' => '{1}munud|]1,Inf[:count munud',
+ 'min' => ':countm',
+ 'second' => '{1}ychydig eiliadau|]1,Inf[:count eiliad',
+ 's' => ':counts',
+ 'ago' => ':time yn ôl',
+ 'from_now' => 'mewn :time',
+ 'after' => ':time ar ôl',
+ 'before' => ':time o\'r blaen',
+ 'diff_now' => 'nawr',
+ 'diff_today' => 'Heddiw',
+ 'diff_today_regexp' => 'Heddiw(?:\\s+am)?',
+ 'diff_yesterday' => 'ddoe',
+ 'diff_yesterday_regexp' => 'Ddoe(?:\\s+am)?',
+ 'diff_tomorrow' => 'yfory',
+ 'diff_tomorrow_regexp' => 'Yfory(?:\\s+am)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Heddiw am] LT',
+ 'nextDay' => '[Yfory am] LT',
+ 'nextWeek' => 'dddd [am] LT',
+ 'lastDay' => '[Ddoe am] LT',
+ 'lastWeek' => 'dddd [diwethaf am] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ return $number.(
+ $number > 20
+ ? (\in_array($number, [40, 50, 60, 80, 100]) ? 'fed' : 'ain')
+ : ([
+ '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
+ 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed', // 11eg to 20fed
+ ])[$number] ?? ''
+ );
+ },
+ 'months' => ['Ionawr', 'Chwefror', 'Mawrth', 'Ebrill', 'Mai', 'Mehefin', 'Gorffennaf', 'Awst', 'Medi', 'Hydref', 'Tachwedd', 'Rhagfyr'],
+ 'months_short' => ['Ion', 'Chwe', 'Maw', 'Ebr', 'Mai', 'Meh', 'Gor', 'Aws', 'Med', 'Hyd', 'Tach', 'Rhag'],
+ 'weekdays' => ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher', 'Dydd Iau', 'Dydd Gwener', 'Dydd Sadwrn'],
+ 'weekdays_short' => ['Sul', 'Llun', 'Maw', 'Mer', 'Iau', 'Gwe', 'Sad'],
+ 'weekdays_min' => ['Su', 'Ll', 'Ma', 'Me', 'Ia', 'Gw', 'Sa'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' a '],
+ 'meridiem' => ['yb', 'yh'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cy_GB.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cy_GB.php
new file mode 100644
index 0000000..541127c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/cy_GB.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/cy.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/da.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/da.php
new file mode 100644
index 0000000..4e6640a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/da.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Rune Mønnike
+ * - François B
+ * - codenhagen
+ * - JD Isaacks
+ * - Jens Herlevsen
+ * - Ulrik McArdle (mcardle)
+ * - Frederik Sauer (FrittenKeeZ)
+ */
+return [
+ 'year' => ':count år|:count år',
+ 'a_year' => 'et år|:count år',
+ 'y' => ':count år|:count år',
+ 'month' => ':count måned|:count måneder',
+ 'a_month' => 'en måned|:count måneder',
+ 'm' => ':count mdr.',
+ 'week' => ':count uge|:count uger',
+ 'a_week' => 'en uge|:count uger',
+ 'w' => ':count u.',
+ 'day' => ':count dag|:count dage',
+ 'a_day' => ':count dag|:count dage',
+ 'd' => ':count d.',
+ 'hour' => ':count time|:count timer',
+ 'a_hour' => 'en time|:count timer',
+ 'h' => ':count t.',
+ 'minute' => ':count minut|:count minutter',
+ 'a_minute' => 'et minut|:count minutter',
+ 'min' => ':count min.',
+ 'second' => ':count sekund|:count sekunder',
+ 'a_second' => 'få sekunder|:count sekunder',
+ 's' => ':count s.',
+ 'ago' => ':time siden',
+ 'from_now' => 'om :time',
+ 'after' => ':time efter',
+ 'before' => ':time før',
+ 'diff_now' => 'nu',
+ 'diff_today' => 'i dag',
+ 'diff_today_regexp' => 'i dag(?:\\s+kl.)?',
+ 'diff_yesterday' => 'i går',
+ 'diff_yesterday_regexp' => 'i går(?:\\s+kl.)?',
+ 'diff_tomorrow' => 'i morgen',
+ 'diff_tomorrow_regexp' => 'i morgen(?:\\s+kl.)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd [d.] D. MMMM YYYY [kl.] HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[i dag kl.] LT',
+ 'nextDay' => '[i morgen kl.] LT',
+ 'nextWeek' => 'på dddd [kl.] LT',
+ 'lastDay' => '[i går kl.] LT',
+ 'lastWeek' => '[i] dddd[s kl.] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['januar', 'februar', 'marts', 'april', 'maj', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'december'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
+ 'weekdays' => ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'],
+ 'weekdays_short' => ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],
+ 'weekdays_min' => ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' og '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/da_DK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/da_DK.php
new file mode 100644
index 0000000..b3bac1a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/da_DK.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/da.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/da_GL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/da_GL.php
new file mode 100644
index 0000000..b2ba81f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/da_GL.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/da.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D. MMM YYYY',
+ 'LLL' => 'D. MMMM YYYY HH.mm',
+ 'LLLL' => 'dddd [den] D. MMMM YYYY HH.mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dav.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dav.php
new file mode 100644
index 0000000..79f021e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dav.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Luma lwa K', 'luma lwa p'],
+ 'weekdays' => ['Ituku ja jumwa', 'Kuramuka jimweri', 'Kuramuka kawi', 'Kuramuka kadadu', 'Kuramuka kana', 'Kuramuka kasanu', 'Kifula nguwo'],
+ 'weekdays_short' => ['Jum', 'Jim', 'Kaw', 'Kad', 'Kan', 'Kas', 'Ngu'],
+ 'weekdays_min' => ['Jum', 'Jim', 'Kaw', 'Kad', 'Kan', 'Kas', 'Ngu'],
+ 'months' => ['Mori ghwa imbiri', 'Mori ghwa kawi', 'Mori ghwa kadadu', 'Mori ghwa kana', 'Mori ghwa kasanu', 'Mori ghwa karandadu', 'Mori ghwa mfungade', 'Mori ghwa wunyanya', 'Mori ghwa ikenda', 'Mori ghwa ikumi', 'Mori ghwa ikumi na imweri', 'Mori ghwa ikumi na iwi'],
+ 'months_short' => ['Imb', 'Kaw', 'Kad', 'Kan', 'Kas', 'Kar', 'Mfu', 'Wun', 'Ike', 'Iku', 'Imw', 'Iwi'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de.php
new file mode 100644
index 0000000..ff00c97
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Michael Hohl
+ * - sheriffmarley
+ * - dennisoderwald
+ * - Timo
+ * - Karag2006
+ * - Pete Scopes (pdscopes)
+ */
+return [
+ 'year' => ':count Jahr|:count Jahre',
+ 'a_year' => 'ein Jahr|:count Jahre',
+ 'y' => ':count J.',
+ 'month' => ':count Monat|:count Monate',
+ 'a_month' => 'ein Monat|:count Monate',
+ 'm' => ':count Mon.',
+ 'week' => ':count Woche|:count Wochen',
+ 'a_week' => 'eine Woche|:count Wochen',
+ 'w' => ':count Wo.',
+ 'day' => ':count Tag|:count Tage',
+ 'a_day' => 'ein Tag|:count Tage',
+ 'd' => ':count Tg.',
+ 'hour' => ':count Stunde|:count Stunden',
+ 'a_hour' => 'eine Stunde|:count Stunden',
+ 'h' => ':count Std.',
+ 'minute' => ':count Minute|:count Minuten',
+ 'a_minute' => 'eine Minute|:count Minuten',
+ 'min' => ':count Min.',
+ 'second' => ':count Sekunde|:count Sekunden',
+ 'a_second' => 'ein paar Sekunden|:count Sekunden',
+ 's' => ':count Sek.',
+ 'millisecond' => ':count Millisekunde|:count Millisekunden',
+ 'a_millisecond' => 'eine Millisekunde|:count Millisekunden',
+ 'ms' => ':countms',
+ 'microsecond' => ':count Mikrosekunde|:count Mikrosekunden',
+ 'a_microsecond' => 'eine Mikrosekunde|:count Mikrosekunden',
+ 'µs' => ':countµs',
+ 'ago' => 'vor :time',
+ 'from_now' => 'in :time',
+ 'after' => ':time später',
+ 'before' => ':time zuvor',
+
+ 'year_from_now' => ':count Jahr|:count Jahren',
+ 'month_from_now' => ':count Monat|:count Monaten',
+ 'week_from_now' => ':count Woche|:count Wochen',
+ 'day_from_now' => ':count Tag|:count Tagen',
+ 'year_ago' => ':count Jahr|:count Jahren',
+ 'month_ago' => ':count Monat|:count Monaten',
+ 'week_ago' => ':count Woche|:count Wochen',
+ 'day_ago' => ':count Tag|:count Tagen',
+ 'a_year_from_now' => 'ein Jahr|:count Jahren',
+ 'a_month_from_now' => 'ein Monat|:count Monaten',
+ 'a_week_from_now' => 'eine Woche|:count Wochen',
+ 'a_day_from_now' => 'ein Tag|:count Tagen',
+ 'a_year_ago' => 'ein Jahr|:count Jahren',
+ 'a_month_ago' => 'ein Monat|:count Monaten',
+ 'a_week_ago' => 'eine Woche|:count Wochen',
+ 'a_day_ago' => 'ein Tag|:count Tagen',
+
+ 'diff_now' => 'Gerade eben',
+ 'diff_today' => 'heute',
+ 'diff_today_regexp' => 'heute(?:\\s+um)?',
+ 'diff_yesterday' => 'Gestern',
+ 'diff_yesterday_regexp' => 'gestern(?:\\s+um)?',
+ 'diff_tomorrow' => 'Morgen',
+ 'diff_tomorrow_regexp' => 'morgen(?:\\s+um)?',
+ 'diff_before_yesterday' => 'Vorgestern',
+ 'diff_after_tomorrow' => 'Übermorgen',
+
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY HH:mm',
+ ],
+
+ 'calendar' => [
+ 'sameDay' => '[heute um] LT [Uhr]',
+ 'nextDay' => '[morgen um] LT [Uhr]',
+ 'nextWeek' => 'dddd [um] LT [Uhr]',
+ 'lastDay' => '[gestern um] LT [Uhr]',
+ 'lastWeek' => '[letzten] dddd [um] LT [Uhr]',
+ 'sameElse' => 'L',
+ ],
+
+ 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
+ 'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
+ 'weekdays' => ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
+ 'weekdays_short' => ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],
+ 'weekdays_min' => ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
+ 'ordinal' => ':number.',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' und '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_AT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_AT.php
new file mode 100644
index 0000000..a2ea4c0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_AT.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - sheriffmarley
+ * - Timo
+ * - Michael Hohl
+ * - Namoshek
+ * - Bernhard Baumrock (BernhardBaumrock)
+ */
+return array_replace_recursive(require __DIR__.'/de.php', [
+ 'months' => [
+ 0 => 'Jänner',
+ ],
+ 'months_short' => [
+ 0 => 'Jän',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_BE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_BE.php
new file mode 100644
index 0000000..8ed8dc6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_BE.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/de.php', [
+ 'formats' => [
+ 'L' => 'YYYY-MM-DD',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_CH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_CH.php
new file mode 100644
index 0000000..a869ab4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_CH.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - sheriffmarley
+ * - Timo
+ * - Michael Hohl
+ */
+return array_replace_recursive(require __DIR__.'/de.php', [
+ 'weekdays_short' => ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_DE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_DE.php
new file mode 100644
index 0000000..fb1209d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_DE.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
+ */
+return require __DIR__.'/de.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_IT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_IT.php
new file mode 100644
index 0000000..604a856
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_IT.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Matthias Dieter Wallno:fer libc-locales@sourceware.org
+ */
+return require __DIR__.'/de.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_LI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_LI.php
new file mode 100644
index 0000000..82edfa1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_LI.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/de.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_LU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_LU.php
new file mode 100644
index 0000000..8ed8dc6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/de_LU.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/de.php', [
+ 'formats' => [
+ 'L' => 'YYYY-MM-DD',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dje.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dje.php
new file mode 100644
index 0000000..08ddbf1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dje.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Subbaahi', 'Zaarikay b'],
+ 'weekdays' => ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamisi', 'Alzuma', 'Asibti'],
+ 'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
+ 'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
+ 'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
+ 'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => ':count hari', // less reliable
+ 'y' => ':count hari', // less reliable
+ 'a_year' => ':count hari', // less reliable
+
+ 'week' => ':count alzuma', // less reliable
+ 'w' => ':count alzuma', // less reliable
+ 'a_week' => ':count alzuma', // less reliable
+
+ 'second' => ':count atinni', // less reliable
+ 's' => ':count atinni', // less reliable
+ 'a_second' => ':count atinni', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/doi.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/doi.php
new file mode 100644
index 0000000..cb679c5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/doi.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/doi_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/doi_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/doi_IN.php
new file mode 100644
index 0000000..d359721
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/doi_IN.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Red Hat Pune libc-alpha@sourceware.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'एप्रैल', 'मेई', 'जून', 'जूलै', 'अगस्त', 'सितंबर', 'अक्तूबर', 'नवंबर', 'दिसंबर'],
+ 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'एप्रैल', 'मेई', 'जून', 'जूलै', 'अगस्त', 'सितंबर', 'अक्तूबर', 'नवंबर', 'दिसंबर'],
+ 'weekdays' => ['ऐतबार', 'सोमबार', 'मंगलबर', 'बुधबार', 'बीरबार', 'शुक्करबार', 'श्नीचरबार'],
+ 'weekdays_short' => ['ऐत', 'सोम', 'मंगल', 'बुध', 'बीर', 'शुक्कर', 'श्नीचर'],
+ 'weekdays_min' => ['ऐत', 'सोम', 'मंगल', 'बुध', 'बीर', 'शुक्कर', 'श्नीचर'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['सञं', 'सबेर'],
+
+ 'second' => ':count सङार', // less reliable
+ 's' => ':count सङार', // less reliable
+ 'a_second' => ':count सङार', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dsb.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dsb.php
new file mode 100644
index 0000000..1d214d5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dsb.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/dsb_DE.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dsb_DE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dsb_DE.php
new file mode 100644
index 0000000..1b94187
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dsb_DE.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Information from Michael Wolf bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'DD. MMMM YYYY',
+ 'LLL' => 'DD. MMMM, HH:mm [góź.]',
+ 'LLLL' => 'dddd, DD. MMMM YYYY, HH:mm [góź.]',
+ ],
+ 'months' => ['januara', 'februara', 'měrca', 'apryla', 'maja', 'junija', 'julija', 'awgusta', 'septembra', 'oktobra', 'nowembra', 'decembra'],
+ 'months_short' => ['Jan', 'Feb', 'Měr', 'Apr', 'Maj', 'Jun', 'Jul', 'Awg', 'Sep', 'Okt', 'Now', 'Dec'],
+ 'weekdays' => ['Njeźela', 'Pónjeźele', 'Wałtora', 'Srjoda', 'Stwórtk', 'Pětk', 'Sobota'],
+ 'weekdays_short' => ['Nj', 'Pó', 'Wa', 'Sr', 'St', 'Pě', 'So'],
+ 'weekdays_min' => ['Nj', 'Pó', 'Wa', 'Sr', 'St', 'Pě', 'So'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'year' => ':count lěto',
+ 'y' => ':count lěto',
+ 'a_year' => ':count lěto',
+
+ 'month' => ':count mjasec',
+ 'm' => ':count mjasec',
+ 'a_month' => ':count mjasec',
+
+ 'week' => ':count tyźeń',
+ 'w' => ':count tyźeń',
+ 'a_week' => ':count tyźeń',
+
+ 'day' => ':count źeń',
+ 'd' => ':count źeń',
+ 'a_day' => ':count źeń',
+
+ 'hour' => ':count góźina',
+ 'h' => ':count góźina',
+ 'a_hour' => ':count góźina',
+
+ 'minute' => ':count minuta',
+ 'min' => ':count minuta',
+ 'a_minute' => ':count minuta',
+
+ 'second' => ':count drugi',
+ 's' => ':count drugi',
+ 'a_second' => ':count drugi',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dua.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dua.php
new file mode 100644
index 0000000..65d712f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dua.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['idiɓa', 'ebyámu'],
+ 'weekdays' => ['éti', 'mɔ́sú', 'kwasú', 'mukɔ́sú', 'ŋgisú', 'ɗónɛsú', 'esaɓasú'],
+ 'weekdays_short' => ['ét', 'mɔ́s', 'kwa', 'muk', 'ŋgi', 'ɗón', 'esa'],
+ 'weekdays_min' => ['ét', 'mɔ́s', 'kwa', 'muk', 'ŋgi', 'ɗón', 'esa'],
+ 'months' => ['dimɔ́di', 'ŋgɔndɛ', 'sɔŋɛ', 'diɓáɓá', 'emiasele', 'esɔpɛsɔpɛ', 'madiɓɛ́díɓɛ́', 'diŋgindi', 'nyɛtɛki', 'mayésɛ́', 'tiníní', 'eláŋgɛ́'],
+ 'months_short' => ['di', 'ŋgɔn', 'sɔŋ', 'diɓ', 'emi', 'esɔ', 'mad', 'diŋ', 'nyɛt', 'may', 'tin', 'elá'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => ':count ma mbu', // less reliable
+ 'y' => ':count ma mbu', // less reliable
+ 'a_year' => ':count ma mbu', // less reliable
+
+ 'month' => ':count myo̱di', // less reliable
+ 'm' => ':count myo̱di', // less reliable
+ 'a_month' => ':count myo̱di', // less reliable
+
+ 'week' => ':count woki', // less reliable
+ 'w' => ':count woki', // less reliable
+ 'a_week' => ':count woki', // less reliable
+
+ 'day' => ':count buńa', // less reliable
+ 'd' => ':count buńa', // less reliable
+ 'a_day' => ':count buńa', // less reliable
+
+ 'hour' => ':count ma awa', // less reliable
+ 'h' => ':count ma awa', // less reliable
+ 'a_hour' => ':count ma awa', // less reliable
+
+ 'minute' => ':count minuti', // less reliable
+ 'min' => ':count minuti', // less reliable
+ 'a_minute' => ':count minuti', // less reliable
+
+ 'second' => ':count maba', // less reliable
+ 's' => ':count maba', // less reliable
+ 'a_second' => ':count maba', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dv.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dv.php
new file mode 100644
index 0000000..a2b60df
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dv.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+$months = [
+ 'ޖެނުއަރީ',
+ 'ފެބްރުއަރީ',
+ 'މާރިޗު',
+ 'އޭޕްރީލު',
+ 'މޭ',
+ 'ޖޫން',
+ 'ޖުލައި',
+ 'އޯގަސްޓު',
+ 'ސެޕްޓެމްބަރު',
+ 'އޮކްޓޯބަރު',
+ 'ނޮވެމްބަރު',
+ 'ޑިސެމްބަރު',
+];
+
+$weekdays = [
+ 'އާދިއްތަ',
+ 'ހޯމަ',
+ 'އަންގާރަ',
+ 'ބުދަ',
+ 'ބުރާސްފަތި',
+ 'ހުކުރު',
+ 'ހޮނިހިރު',
+];
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - Jawish Hameed
+ */
+return [
+ 'year' => ':count '.'އަހަރު',
+ 'a_year' => '{1}'.'އަހަރެއް'.'|:count '.'އަހަރު',
+ 'month' => ':count '.'މަސް',
+ 'a_month' => '{1}'.'މަހެއް'.'|:count '.'މަސް',
+ 'week' => ':count '.'ހަފްތާ',
+ 'a_week' => '{1}'.'ސިކުންތުކޮޅެއް'.'|:count '.'ހަފްތާ',
+ 'day' => ':count '.'ދުވަސް',
+ 'a_day' => '{1}'.'ދުވަހެއް'.'|:count '.'ދުވަސް',
+ 'hour' => ':count '.'ގަޑިއިރު',
+ 'a_hour' => '{1}'.'ގަޑިއިރެއް'.'|:count '.'ގަޑިއިރު',
+ 'minute' => ':count '.'މިނިޓު',
+ 'a_minute' => '{1}'.'މިނިޓެއް'.'|:count '.'މިނިޓު',
+ 'second' => ':count '.'ސިކުންތު',
+ 'a_second' => '{1}'.'ސިކުންތުކޮޅެއް'.'|:count '.'ސިކުންތު',
+ 'ago' => 'ކުރިން :time',
+ 'from_now' => 'ތެރޭގައި :time',
+ 'after' => ':time ފަހުން',
+ 'before' => ':time ކުރި',
+ 'diff_yesterday' => 'އިއްޔެ',
+ 'diff_today' => 'މިއަދު',
+ 'diff_tomorrow' => 'މާދަމާ',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[މިއަދު] LT',
+ 'nextDay' => '[މާދަމާ] LT',
+ 'nextWeek' => 'dddd LT',
+ 'lastDay' => '[އިއްޔެ] LT',
+ 'lastWeek' => '[ފާއިތުވި] dddd LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['މކ', 'މފ'],
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => $weekdays,
+ 'weekdays_short' => $weekdays,
+ 'weekdays_min' => ['އާދި', 'ހޯމަ', 'އަން', 'ބުދަ', 'ބުރާ', 'ހުކު', 'ހޮނި'],
+ 'list' => [', ', ' އަދި '],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php
new file mode 100644
index 0000000..208fb5a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Ahmed Ali <ajaaibu@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ahmed Ali
+ */
+
+$months = [
+ 'ޖެނުއަރީ',
+ 'ފެބްރުއަރީ',
+ 'މާރިޗު',
+ 'އޭޕްރީލު',
+ 'މޭ',
+ 'ޖޫން',
+ 'ޖުލައި',
+ 'އޯގަސްޓު',
+ 'ސެޕްޓެމްބަރު',
+ 'އޮކްޓޯބަރު',
+ 'ނޮވެމްބަރު',
+ 'ޑިސެމްބަރު',
+];
+
+$weekdays = [
+ 'އާދިއްތަ',
+ 'ހޯމަ',
+ 'އަންގާރަ',
+ 'ބުދަ',
+ 'ބުރާސްފަތި',
+ 'ހުކުރު',
+ 'ހޮނިހިރު',
+];
+
+return [
+ 'year' => '{0}އަހަރެއް|[1,Inf]:count އަހަރު',
+ 'y' => '{0}އަހަރެއް|[1,Inf]:count އަހަރު',
+ 'month' => '{0}މައްސަރެއް|[1,Inf]:count މަސް',
+ 'm' => '{0}މައްސަރެއް|[1,Inf]:count މަސް',
+ 'week' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ',
+ 'w' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ',
+ 'day' => '{0}ދުވަސް|[1,Inf]:count ދުވަސް',
+ 'd' => '{0}ދުވަސް|[1,Inf]:count ދުވަސް',
+ 'hour' => '{0}ގަޑިއިރެއް|[1,Inf]:count ގަޑި',
+ 'h' => '{0}ގަޑިއިރެއް|[1,Inf]:count ގަޑި',
+ 'minute' => '{0}މިނެޓެއް|[1,Inf]:count މިނެޓް',
+ 'min' => '{0}މިނެޓެއް|[1,Inf]:count މިނެޓް',
+ 'second' => '{0}ސިކުންތެއް|[1,Inf]:count ސިކުންތު',
+ 's' => '{0}ސިކުންތެއް|[1,Inf]:count ސިކުންތު',
+ 'ago' => ':time ކުރިން',
+ 'from_now' => ':time ފަހުން',
+ 'after' => ':time ފަހުން',
+ 'before' => ':time ކުރި',
+ 'diff_yesterday' => 'އިއްޔެ',
+ 'diff_today' => 'މިއަދު',
+ 'diff_tomorrow' => 'މާދަމާ',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[މިއަދު] LT',
+ 'nextDay' => '[މާދަމާ] LT',
+ 'nextWeek' => 'dddd LT',
+ 'lastDay' => '[އިއްޔެ] LT',
+ 'lastWeek' => '[ފާއިތުވި] dddd LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['މކ', 'މފ'],
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => $weekdays,
+ 'weekdays_short' => $weekdays,
+ 'weekdays_min' => ['އާދި', 'ހޯމަ', 'އަން', 'ބުދަ', 'ބުރާ', 'ހުކު', 'ހޮނި'],
+ 'list' => [', ', ' އަދި '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dyo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dyo.php
new file mode 100644
index 0000000..ecb649b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dyo.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'weekdays' => ['Dimas', 'Teneŋ', 'Talata', 'Alarbay', 'Aramisay', 'Arjuma', 'Sibiti'],
+ 'weekdays_short' => ['Dim', 'Ten', 'Tal', 'Ala', 'Ara', 'Arj', 'Sib'],
+ 'weekdays_min' => ['Dim', 'Ten', 'Tal', 'Ala', 'Ara', 'Arj', 'Sib'],
+ 'months' => ['Sanvie', 'Fébirie', 'Mars', 'Aburil', 'Mee', 'Sueŋ', 'Súuyee', 'Ut', 'Settembar', 'Oktobar', 'Novembar', 'Disambar'],
+ 'months_short' => ['Sa', 'Fe', 'Ma', 'Ab', 'Me', 'Su', 'Sú', 'Ut', 'Se', 'Ok', 'No', 'De'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dz.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dz.php
new file mode 100644
index 0000000..cc17e69
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dz.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/dz_BT.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dz_BT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dz_BT.php
new file mode 100644
index 0000000..bfbcaf4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/dz_BT.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Sherubtse College bug-glibc@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'པསྱི་ལོYYཟལMMཚེསDD',
+ ],
+ 'months' => ['ཟླ་བ་དང་པ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་ཕ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུནཔ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'],
+ 'months_short' => ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣', 'ཟླ་༤', 'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧', 'ཟླ་༨', 'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡', 'ཟླ་༡༢'],
+ 'weekdays' => ['གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་ཕ་', 'གཟའ་པུར་བུ་', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་ཕ་', 'གཟའ་ཉི་མ་'],
+ 'weekdays_short' => ['ཟླ་', 'མིར་', 'ལྷག་', 'པུར་', 'སངས་', 'སྤེན་', 'ཉི་'],
+ 'weekdays_min' => ['ཟླ་', 'མིར་', 'ལྷག་', 'པུར་', 'སངས་', 'སྤེན་', 'ཉི་'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ངས་ཆ', 'ཕྱི་ཆ'],
+
+ 'year' => ':count ཆརཔ', // less reliable
+ 'y' => ':count ཆརཔ', // less reliable
+ 'a_year' => ':count ཆརཔ', // less reliable
+
+ 'month' => ':count ཟླ་བ', // less reliable
+ 'm' => ':count ཟླ་བ', // less reliable
+ 'a_month' => ':count ཟླ་བ', // less reliable
+
+ 'day' => ':count ཉི', // less reliable
+ 'd' => ':count ཉི', // less reliable
+ 'a_day' => ':count ཉི', // less reliable
+
+ 'second' => ':count ཆ', // less reliable
+ 's' => ':count ཆ', // less reliable
+ 'a_second' => ':count ཆ', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ebu.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ebu.php
new file mode 100644
index 0000000..5aab48d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ebu.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['KI', 'UT'],
+ 'weekdays' => ['Kiumia', 'Njumatatu', 'Njumaine', 'Njumatano', 'Aramithi', 'Njumaa', 'NJumamothii'],
+ 'weekdays_short' => ['Kma', 'Tat', 'Ine', 'Tan', 'Arm', 'Maa', 'NMM'],
+ 'weekdays_min' => ['Kma', 'Tat', 'Ine', 'Tan', 'Arm', 'Maa', 'NMM'],
+ 'months' => ['Mweri wa mbere', 'Mweri wa kaĩri', 'Mweri wa kathatũ', 'Mweri wa kana', 'Mweri wa gatano', 'Mweri wa gatantatũ', 'Mweri wa mũgwanja', 'Mweri wa kanana', 'Mweri wa kenda', 'Mweri wa ikũmi', 'Mweri wa ikũmi na ũmwe', 'Mweri wa ikũmi na Kaĩrĩ'],
+ 'months_short' => ['Mbe', 'Kai', 'Kat', 'Kan', 'Gat', 'Gan', 'Mug', 'Knn', 'Ken', 'Iku', 'Imw', 'Igi'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ee.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ee.php
new file mode 100644
index 0000000..2fd9dcd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ee.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['ŋ', 'ɣ'],
+ 'weekdays' => ['kɔsiɖa', 'dzoɖa', 'blaɖa', 'kuɖa', 'yawoɖa', 'fiɖa', 'memleɖa'],
+ 'weekdays_short' => ['kɔs', 'dzo', 'bla', 'kuɖ', 'yaw', 'fiɖ', 'mem'],
+ 'weekdays_min' => ['kɔs', 'dzo', 'bla', 'kuɖ', 'yaw', 'fiɖ', 'mem'],
+ 'months' => ['dzove', 'dzodze', 'tedoxe', 'afɔfĩe', 'dama', 'masa', 'siamlɔm', 'deasiamime', 'anyɔnyɔ', 'kele', 'adeɛmekpɔxe', 'dzome'],
+ 'months_short' => ['dzv', 'dzd', 'ted', 'afɔ', 'dam', 'mas', 'sia', 'dea', 'any', 'kel', 'ade', 'dzm'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'a [ga] h:mm',
+ 'LTS' => 'a [ga] h:mm:ss',
+ 'L' => 'M/D/YYYY',
+ 'LL' => 'MMM D [lia], YYYY',
+ 'LLL' => 'a [ga] h:mm MMMM D [lia] YYYY',
+ 'LLLL' => 'a [ga] h:mm dddd, MMMM D [lia] YYYY',
+ ],
+
+ 'year' => 'ƒe :count',
+ 'y' => 'ƒe :count',
+ 'a_year' => 'ƒe :count',
+
+ 'month' => 'ɣleti :count',
+ 'm' => 'ɣleti :count',
+ 'a_month' => 'ɣleti :count',
+
+ 'week' => 'kwasiɖa :count',
+ 'w' => 'kwasiɖa :count',
+ 'a_week' => 'kwasiɖa :count',
+
+ 'day' => 'ŋkeke :count',
+ 'd' => 'ŋkeke :count',
+ 'a_day' => 'ŋkeke :count',
+
+ 'hour' => 'gaƒoƒo :count',
+ 'h' => 'gaƒoƒo :count',
+ 'a_hour' => 'gaƒoƒo :count',
+
+ 'minute' => 'miniti :count', // less reliable
+ 'min' => 'miniti :count', // less reliable
+ 'a_minute' => 'miniti :count', // less reliable
+
+ 'second' => 'sɛkɛnd :count', // less reliable
+ 's' => 'sɛkɛnd :count', // less reliable
+ 'a_second' => 'sɛkɛnd :count', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ee_TG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ee_TG.php
new file mode 100644
index 0000000..02d77e6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ee_TG.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ee.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'LLL' => 'HH:mm MMMM D [lia] YYYY',
+ 'LLLL' => 'HH:mm dddd, MMMM D [lia] YYYY',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/el.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/el.php
new file mode 100644
index 0000000..09cf7e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/el.php
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Alessandro Di Felice
+ * - François B
+ * - Tim Fish
+ * - Gabriel Monteagudo
+ * - JD Isaacks
+ * - yiannisdesp
+ * - Ilias Kasmeridis (iliaskasm)
+ */
+return [
+ 'year' => ':count χρόνος|:count χρόνια',
+ 'a_year' => 'ένας χρόνος|:count χρόνια',
+ 'y' => ':count χρ.',
+ 'month' => ':count μήνας|:count μήνες',
+ 'a_month' => 'ένας μήνας|:count μήνες',
+ 'm' => ':count μήν.',
+ 'week' => ':count εβδομάδα|:count εβδομάδες',
+ 'a_week' => 'μια εβδομάδα|:count εβδομάδες',
+ 'w' => ':count εβδ.',
+ 'day' => ':count μέρα|:count μέρες',
+ 'a_day' => 'μία μέρα|:count μέρες',
+ 'd' => ':count μέρ.',
+ 'hour' => ':count ώρα|:count ώρες',
+ 'a_hour' => 'μία ώρα|:count ώρες',
+ 'h' => ':count ώρα|:count ώρες',
+ 'minute' => ':count λεπτό|:count λεπτά',
+ 'a_minute' => 'ένα λεπτό|:count λεπτά',
+ 'min' => ':count λεπ.',
+ 'second' => ':count δευτερόλεπτο|:count δευτερόλεπτα',
+ 'a_second' => 'λίγα δευτερόλεπτα|:count δευτερόλεπτα',
+ 's' => ':count δευ.',
+ 'ago' => 'πριν :time',
+ 'from_now' => 'σε :time',
+ 'after' => ':time μετά',
+ 'before' => ':time πριν',
+ 'diff_now' => 'τώρα',
+ 'diff_today' => 'Σήμερα',
+ 'diff_today_regexp' => 'Σήμερα(?:\\s+{})?',
+ 'diff_yesterday' => 'χθες',
+ 'diff_yesterday_regexp' => 'Χθες(?:\\s+{})?',
+ 'diff_tomorrow' => 'αύριο',
+ 'diff_tomorrow_regexp' => 'Αύριο(?:\\s+{})?',
+ 'formats' => [
+ 'LT' => 'h:mm A',
+ 'LTS' => 'h:mm:ss A',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm A',
+ 'LLLL' => 'dddd, D MMMM YYYY h:mm A',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Σήμερα {}] LT',
+ 'nextDay' => '[Αύριο {}] LT',
+ 'nextWeek' => 'dddd [{}] LT',
+ 'lastDay' => '[Χθες {}] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $current) {
+ switch ($current->dayOfWeek) {
+ case 6:
+ return '[το προηγούμενο] dddd [{}] LT';
+ default:
+ return '[την προηγούμενη] dddd [{}] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numberη',
+ 'meridiem' => ['ΠΜ', 'ΜΜ', 'πμ', 'μμ'],
+ 'months' => ['Ιανουαρίου', 'Φεβρουαρίου', 'Μαρτίου', 'Απριλίου', 'Μαΐου', 'Ιουνίου', 'Ιουλίου', 'Αυγούστου', 'Σεπτεμβρίου', 'Οκτωβρίου', 'Νοεμβρίου', 'Δεκεμβρίου'],
+ 'months_standalone' => ['Ιανουάριος', 'Φεβρουάριος', 'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος', 'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος', 'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος'],
+ 'months_regexp' => '/(D[oD]?[\s,]+MMMM|L{2,4}|l{2,4})/',
+ 'months_short' => ['Ιαν', 'Φεβ', 'Μαρ', 'Απρ', 'Μαϊ', 'Ιουν', 'Ιουλ', 'Αυγ', 'Σεπ', 'Οκτ', 'Νοε', 'Δεκ'],
+ 'weekdays' => ['Κυριακή', 'Δευτέρα', 'Τρίτη', 'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σάββατο'],
+ 'weekdays_short' => ['Κυρ', 'Δευ', 'Τρι', 'Τετ', 'Πεμ', 'Παρ', 'Σαβ'],
+ 'weekdays_min' => ['Κυ', 'Δε', 'Τρ', 'Τε', 'Πε', 'Πα', 'Σα'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' και '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/el_CY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/el_CY.php
new file mode 100644
index 0000000..8a693c1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/el_CY.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Greek Debian Translation Team bug-glibc@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/el.php', [
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/el_GR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/el_GR.php
new file mode 100644
index 0000000..df196af
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/el_GR.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/el.php', [
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en.php
new file mode 100644
index 0000000..a8633fe
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Milos Sakovic
+ * - Paul
+ * - Pete Scopes (pdscopes)
+ */
+return [
+ /*
+ * {1}, {0} and ]1,Inf[ are not needed as it's the default for English pluralization.
+ * But as some languages are using en.php as a fallback, it's better to specify it
+ * explicitly so those languages also fallback to English pluralization when a unit
+ * is missing.
+ */
+ 'year' => '{1}:count year|{0}:count years|]1,Inf[:count years',
+ 'a_year' => '{1}a year|{0}:count years|]1,Inf[:count years',
+ 'y' => '{1}:countyr|{0}:countyrs|]1,Inf[:countyrs',
+ 'month' => '{1}:count month|{0}:count months|]1,Inf[:count months',
+ 'a_month' => '{1}a month|{0}:count months|]1,Inf[:count months',
+ 'm' => '{1}:countmo|{0}:countmos|]1,Inf[:countmos',
+ 'week' => '{1}:count week|{0}:count weeks|]1,Inf[:count weeks',
+ 'a_week' => '{1}a week|{0}:count weeks|]1,Inf[:count weeks',
+ 'w' => ':countw',
+ 'day' => '{1}:count day|{0}:count days|]1,Inf[:count days',
+ 'a_day' => '{1}a day|{0}:count days|]1,Inf[:count days',
+ 'd' => ':countd',
+ 'hour' => '{1}:count hour|{0}:count hours|]1,Inf[:count hours',
+ 'a_hour' => '{1}an hour|{0}:count hours|]1,Inf[:count hours',
+ 'h' => ':counth',
+ 'minute' => '{1}:count minute|{0}:count minutes|]1,Inf[:count minutes',
+ 'a_minute' => '{1}a minute|{0}:count minutes|]1,Inf[:count minutes',
+ 'min' => ':countm',
+ 'second' => '{1}:count second|{0}:count seconds|]1,Inf[:count seconds',
+ 'a_second' => '{1}a few seconds|{0}:count seconds|]1,Inf[:count seconds',
+ 's' => ':counts',
+ 'millisecond' => '{1}:count millisecond|{0}:count milliseconds|]1,Inf[:count milliseconds',
+ 'a_millisecond' => '{1}a millisecond|{0}:count milliseconds|]1,Inf[:count milliseconds',
+ 'ms' => ':countms',
+ 'microsecond' => '{1}:count microsecond|{0}:count microseconds|]1,Inf[:count microseconds',
+ 'a_microsecond' => '{1}a microsecond|{0}:count microseconds|]1,Inf[:count microseconds',
+ 'µs' => ':countµs',
+ 'ago' => ':time ago',
+ 'from_now' => ':time from now',
+ 'after' => ':time after',
+ 'before' => ':time before',
+ 'diff_now' => 'just now',
+ 'diff_today' => 'today',
+ 'diff_yesterday' => 'yesterday',
+ 'diff_tomorrow' => 'tomorrow',
+ 'diff_before_yesterday' => 'before yesterday',
+ 'diff_after_tomorrow' => 'after tomorrow',
+ 'period_recurrences' => '{1}once|{0}:count times|]1,Inf[:count times',
+ 'period_interval' => 'every :interval',
+ 'period_start_date' => 'from :date',
+ 'period_end_date' => 'to :date',
+ 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ 'weekdays' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+ 'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+ 'weekdays_min' => ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
+ 'ordinal' => function ($number) {
+ $lastDigit = $number % 10;
+
+ return $number.(
+ (~~($number % 100 / 10) === 1) ? 'th' : (
+ ($lastDigit === 1) ? 'st' : (
+ ($lastDigit === 2) ? 'nd' : (
+ ($lastDigit === 3) ? 'rd' : 'th'
+ )
+ )
+ )
+ );
+ },
+ 'list' => [', ', ' and '],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_001.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_001.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_001.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_150.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_150.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_150.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AG.php
new file mode 100644
index 0000000..2c1c64f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AG.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AI.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AI.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AS.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AS.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AT.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AT.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AU.php
new file mode 100644
index 0000000..f16bd4f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_AU.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kunal Marwaha
+ * - François B
+ * - Mayank Badola
+ * - JD Isaacks
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'from_now' => 'in :time',
+ 'formats' => [
+ 'LT' => 'h:mm A',
+ 'LTS' => 'h:mm:ss A',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm A',
+ 'LLLL' => 'dddd, D MMMM YYYY h:mm A',
+ ],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BB.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BB.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BB.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BE.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BE.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BI.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BI.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BM.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BM.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BS.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BS.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BW.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BW.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BZ.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_BZ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CA.php
new file mode 100644
index 0000000..e656086
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CA.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Zhan Tong Zhang
+ * - Mayank Badola
+ * - JD Isaacks
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'from_now' => 'in :time',
+ 'formats' => [
+ 'LT' => 'h:mm A',
+ 'LTS' => 'h:mm:ss A',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'MMMM D, YYYY',
+ 'LLL' => 'MMMM D, YYYY h:mm A',
+ 'LLLL' => 'dddd, MMMM D, YYYY h:mm A',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CC.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CC.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CH.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CH.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CK.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CK.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CM.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CM.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CX.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CX.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CX.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CY.php
new file mode 100644
index 0000000..a44c350
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_CY.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - NehaGautam
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'from_now' => 'in :time',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD-MM-YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DE.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DE.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DG.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DG.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DK.php
new file mode 100644
index 0000000..9e8a8c6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DK.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Danish Standards Association bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY-MM-DD',
+ ],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DM.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_DM.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ER.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ER.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ER.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FI.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FI.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FJ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FJ.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FJ.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FK.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FK.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FM.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_FM.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GB.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GB.php
new file mode 100644
index 0000000..67d9fd6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GB.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Mayank Badola
+ * - JD Isaacks
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'from_now' => 'in :time',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GD.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GD.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GG.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GG.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GH.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GH.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GI.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GI.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GM.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GM.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GU.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GU.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GY.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_GY.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_HK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_HK.php
new file mode 100644
index 0000000..34aae98
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_HK.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IE.php
new file mode 100644
index 0000000..c8d3c2f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IE.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Martin McWhorter
+ * - François B
+ * - Chris Cartlidge
+ * - JD Isaacks
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'from_now' => 'in :time',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD-MM-YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IL.php
new file mode 100644
index 0000000..e607924
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IL.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Yoav Amit
+ * - François B
+ * - Mayank Badola
+ * - JD Isaacks
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'from_now' => 'in :time',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IM.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IM.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IN.php
new file mode 100644
index 0000000..00414e9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IN.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YY',
+ 'LL' => 'MMMM DD, YYYY',
+ 'LLL' => 'DD MMM HH:mm',
+ 'LLLL' => 'MMMM DD, YYYY HH:mm',
+ ],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IO.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_IO.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ISO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ISO.php
new file mode 100644
index 0000000..6ae11c9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ISO.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-dd',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'YYYY MMMM D HH:mm',
+ 'LLLL' => 'dddd, YYYY MMMM DD HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_JE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_JE.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_JE.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_JM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_JM.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_JM.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KE.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KE.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KI.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KI.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KN.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KN.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KY.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_KY.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_LC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_LC.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_LC.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_LR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_LR.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_LR.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_LS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_LS.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_LS.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MG.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MG.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MH.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MH.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MO.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MO.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MP.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MP.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MP.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MS.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MS.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MT.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MT.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MU.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MU.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MW.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MW.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MY.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_MY.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NA.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NA.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NF.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NF.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NF.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NG.php
new file mode 100644
index 0000000..1d0d34f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NG.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NL.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NL.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NR.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NR.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NU.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NU.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NZ.php
new file mode 100644
index 0000000..6a206a0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_NZ.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Mayank Badola
+ * - Luke McGregor
+ * - JD Isaacks
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'from_now' => 'in :time',
+ 'formats' => [
+ 'LT' => 'h:mm A',
+ 'LTS' => 'h:mm:ss A',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm A',
+ 'LLLL' => 'dddd, D MMMM YYYY h:mm A',
+ ],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PG.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PG.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PH.php
new file mode 100644
index 0000000..34aae98
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PH.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PK.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PK.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PN.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PN.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PR.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PR.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PW.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_PW.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_RW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_RW.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_RW.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SB.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SB.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SB.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SC.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SC.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SD.php
new file mode 100644
index 0000000..ce4780c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SD.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 6,
+ 'weekend' => [5, 6],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SE.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SE.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SG.php
new file mode 100644
index 0000000..ed0b3f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SG.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'from_now' => 'in :time',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SH.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SH.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SI.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SI.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SL.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SL.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SS.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SS.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SX.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SX.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SX.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SZ.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_SZ.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TC.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TC.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TK.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TK.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TO.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TO.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TT.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TT.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TV.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TV.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TV.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TZ.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_TZ.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_UG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_UG.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_UG.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_UM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_UM.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_UM.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_US.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_US.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_US.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_US_Posix.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_US_Posix.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_US_Posix.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VC.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VC.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VG.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VG.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VI.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VI.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VU.php
new file mode 100644
index 0000000..9f2a3f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_VU.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_WS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_WS.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_WS.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ZA.php
new file mode 100644
index 0000000..48ea947
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ZA.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YY',
+ 'LL' => 'MMMM DD, YYYY',
+ 'LLL' => 'DD MMM HH:mm',
+ 'LLLL' => 'MMMM DD, YYYY HH:mm',
+ ],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ZM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ZM.php
new file mode 100644
index 0000000..d8a8cb5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ZM.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - ANLoc Martin Benjamin locales@africanlocalization.net
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ZW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ZW.php
new file mode 100644
index 0000000..31f60e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/en_ZW.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/en.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/eo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/eo.php
new file mode 100644
index 0000000..7c2efba
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/eo.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - Mia Nordentoft
+ * - JD Isaacks
+ */
+return [
+ 'year' => ':count jaro|:count jaroj',
+ 'a_year' => 'jaro|:count jaroj',
+ 'y' => ':count j.',
+ 'month' => ':count monato|:count monatoj',
+ 'a_month' => 'monato|:count monatoj',
+ 'm' => ':count mo.',
+ 'week' => ':count semajno|:count semajnoj',
+ 'a_week' => 'semajno|:count semajnoj',
+ 'w' => ':count sem.',
+ 'day' => ':count tago|:count tagoj',
+ 'a_day' => 'tago|:count tagoj',
+ 'd' => ':count t.',
+ 'hour' => ':count horo|:count horoj',
+ 'a_hour' => 'horo|:count horoj',
+ 'h' => ':count h.',
+ 'minute' => ':count minuto|:count minutoj',
+ 'a_minute' => 'minuto|:count minutoj',
+ 'min' => ':count min.',
+ 'second' => ':count sekundo|:count sekundoj',
+ 'a_second' => 'sekundoj|:count sekundoj',
+ 's' => ':count sek.',
+ 'ago' => 'antaŭ :time',
+ 'from_now' => 'post :time',
+ 'after' => ':time poste',
+ 'before' => ':time antaŭe',
+ 'diff_yesterday' => 'Hieraŭ',
+ 'diff_yesterday_regexp' => 'Hieraŭ(?:\\s+je)?',
+ 'diff_today' => 'Hodiaŭ',
+ 'diff_today_regexp' => 'Hodiaŭ(?:\\s+je)?',
+ 'diff_tomorrow' => 'Morgaŭ',
+ 'diff_tomorrow_regexp' => 'Morgaŭ(?:\\s+je)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'D[-a de] MMMM, YYYY',
+ 'LLL' => 'D[-a de] MMMM, YYYY HH:mm',
+ 'LLLL' => 'dddd, [la] D[-a de] MMMM, YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Hodiaŭ je] LT',
+ 'nextDay' => '[Morgaŭ je] LT',
+ 'nextWeek' => 'dddd [je] LT',
+ 'lastDay' => '[Hieraŭ je] LT',
+ 'lastWeek' => '[pasinta] dddd [je] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numbera',
+ 'meridiem' => ['a.t.m.', 'p.t.m.'],
+ 'months' => ['januaro', 'februaro', 'marto', 'aprilo', 'majo', 'junio', 'julio', 'aŭgusto', 'septembro', 'oktobro', 'novembro', 'decembro'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aŭg', 'sep', 'okt', 'nov', 'dec'],
+ 'weekdays' => ['dimanĉo', 'lundo', 'mardo', 'merkredo', 'ĵaŭdo', 'vendredo', 'sabato'],
+ 'weekdays_short' => ['dim', 'lun', 'mard', 'merk', 'ĵaŭ', 'ven', 'sab'],
+ 'weekdays_min' => ['di', 'lu', 'ma', 'me', 'ĵa', 've', 'sa'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' kaj '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es.php
new file mode 100644
index 0000000..daaf257
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kunal Marwaha
+ * - kostas
+ * - François B
+ * - Tim Fish
+ * - Claire Coloma
+ * - Steven Heinrich
+ * - JD Isaacks
+ * - Raphael Amorim
+ * - Jorge Y. Castillo
+ * - Víctor Díaz
+ * - Diego
+ * - Sebastian Thierer
+ * - quinterocesar
+ * - Daniel Commesse Liévanos (danielcommesse)
+ * - Pete Scopes (pdscopes)
+ */
+return [
+ 'year' => ':count año|:count años',
+ 'a_year' => 'un año|:count años',
+ 'y' => ':count año|:count años',
+ 'month' => ':count mes|:count meses',
+ 'a_month' => 'un mes|:count meses',
+ 'm' => ':count mes|:count meses',
+ 'week' => ':count semana|:count semanas',
+ 'a_week' => 'una semana|:count semanas',
+ 'w' => ':countsem',
+ 'day' => ':count día|:count días',
+ 'a_day' => 'un día|:count días',
+ 'd' => ':countd',
+ 'hour' => ':count hora|:count horas',
+ 'a_hour' => 'una hora|:count horas',
+ 'h' => ':counth',
+ 'minute' => ':count minuto|:count minutos',
+ 'a_minute' => 'un minuto|:count minutos',
+ 'min' => ':countm',
+ 'second' => ':count segundo|:count segundos',
+ 'a_second' => 'unos segundos|:count segundos',
+ 's' => ':counts',
+ 'millisecond' => ':count milisegundo|:count milisegundos',
+ 'a_millisecond' => 'un milisegundo|:count milisegundos',
+ 'ms' => ':countms',
+ 'microsecond' => ':count microsegundo|:count microsegundos',
+ 'a_microsecond' => 'un microsegundo|:count microsegundos',
+ 'µs' => ':countµs',
+ 'ago' => 'hace :time',
+ 'from_now' => 'en :time',
+ 'after' => ':time después',
+ 'before' => ':time antes',
+ 'diff_now' => 'ahora mismo',
+ 'diff_today' => 'hoy',
+ 'diff_today_regexp' => 'hoy(?:\\s+a)?(?:\\s+las)?',
+ 'diff_yesterday' => 'ayer',
+ 'diff_yesterday_regexp' => 'ayer(?:\\s+a)?(?:\\s+las)?',
+ 'diff_tomorrow' => 'mañana',
+ 'diff_tomorrow_regexp' => 'mañana(?:\\s+a)?(?:\\s+las)?',
+ 'diff_before_yesterday' => 'anteayer',
+ 'diff_after_tomorrow' => 'pasado mañana',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D [de] MMMM [de] YYYY',
+ 'LLL' => 'D [de] MMMM [de] YYYY H:mm',
+ 'LLLL' => 'dddd, D [de] MMMM [de] YYYY H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => function (\Carbon\CarbonInterface $current) {
+ return '[hoy a la'.($current->hour !== 1 ? 's' : '').'] LT';
+ },
+ 'nextDay' => function (\Carbon\CarbonInterface $current) {
+ return '[mañana a la'.($current->hour !== 1 ? 's' : '').'] LT';
+ },
+ 'nextWeek' => function (\Carbon\CarbonInterface $current) {
+ return 'dddd [a la'.($current->hour !== 1 ? 's' : '').'] LT';
+ },
+ 'lastDay' => function (\Carbon\CarbonInterface $current) {
+ return '[ayer a la'.($current->hour !== 1 ? 's' : '').'] LT';
+ },
+ 'lastWeek' => function (\Carbon\CarbonInterface $current) {
+ return '[el] dddd [pasado a la'.($current->hour !== 1 ? 's' : '').'] LT';
+ },
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
+ 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
+ 'mmm_suffix' => '.',
+ 'ordinal' => ':numberº',
+ 'weekdays' => ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'],
+ 'weekdays_short' => ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
+ 'weekdays_min' => ['do', 'lu', 'ma', 'mi', 'ju', 'vi', 'sá'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' y '],
+ 'meridiem' => ['a. m.', 'p. m.'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_419.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_419.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_419.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_AR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_AR.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_AR.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_BO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_BO.php
new file mode 100644
index 0000000..c9b8432
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_BO.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_BR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_BR.php
new file mode 100644
index 0000000..e9dbe2b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_BR.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_BZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_BZ.php
new file mode 100644
index 0000000..e9dbe2b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_BZ.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CL.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CL.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CO.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CO.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CR.php
new file mode 100644
index 0000000..553fc09
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CR.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CU.php
new file mode 100644
index 0000000..96391d4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_CU.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_DO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_DO.php
new file mode 100644
index 0000000..0f855ba
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_DO.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - kostas
+ * - François B
+ * - Tim Fish
+ * - Chiel Robben
+ * - Claire Coloma
+ * - Steven Heinrich
+ * - JD Isaacks
+ * - Raphael Amorim
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'diff_before_yesterday' => 'anteayer',
+ 'formats' => [
+ 'LT' => 'h:mm A',
+ 'LTS' => 'h:mm:ss A',
+ 'LLL' => 'D [de] MMMM [de] YYYY h:mm A',
+ 'LLLL' => 'dddd, D [de] MMMM [de] YYYY h:mm A',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_EA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_EA.php
new file mode 100644
index 0000000..96391d4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_EA.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_EC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_EC.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_EC.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_ES.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_ES.php
new file mode 100644
index 0000000..19217c2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_ES.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return require __DIR__.'/es.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_GQ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_GQ.php
new file mode 100644
index 0000000..96391d4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_GQ.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_GT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_GT.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_GT.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_HN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_HN.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_HN.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_IC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_IC.php
new file mode 100644
index 0000000..96391d4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_IC.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_MX.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_MX.php
new file mode 100644
index 0000000..61e14cf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_MX.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'diff_before_yesterday' => 'antier',
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_NI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_NI.php
new file mode 100644
index 0000000..6b964c1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_NI.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PA.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PA.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PE.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PE.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PH.php
new file mode 100644
index 0000000..ea345b2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PH.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'D/M/yy',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D [de] MMMM [de] YYYY h:mm a',
+ 'LLLL' => 'dddd, D [de] MMMM [de] YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PR.php
new file mode 100644
index 0000000..6b964c1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PR.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PY.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_PY.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_SV.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_SV.php
new file mode 100644
index 0000000..00db08e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_SV.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
+ 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_US.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_US.php
new file mode 100644
index 0000000..f333136
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_US.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kunal Marwaha
+ * - Josh Soref
+ * - Jørn Ølmheim
+ * - Craig Patik
+ * - bustta
+ * - François B
+ * - Tim Fish
+ * - Claire Coloma
+ * - Steven Heinrich
+ * - JD Isaacks
+ * - Raphael Amorim
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'diff_before_yesterday' => 'anteayer',
+ 'formats' => [
+ 'LT' => 'h:mm A',
+ 'LTS' => 'h:mm:ss A',
+ 'L' => 'MM/DD/YYYY',
+ 'LL' => 'MMMM [de] D [de] YYYY',
+ 'LLL' => 'MMMM [de] D [de] YYYY h:mm A',
+ 'LLLL' => 'dddd, MMMM [de] D [de] YYYY h:mm A',
+ ],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_UY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_UY.php
new file mode 100644
index 0000000..39baff8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_UY.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
+ 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'set', 'oct', 'nov', 'dic'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_VE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_VE.php
new file mode 100644
index 0000000..a74806e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/es_VE.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/es.php', [
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/et.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/et.php
new file mode 100644
index 0000000..f49c880
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/et.php
@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - Andres Ivanov
+ * - Tsutomu Kuroda
+ * - tjku
+ * - Max Melentiev
+ * - Juanito Fatas
+ * - RM87
+ * - Akira Matsuda
+ * - Christopher Dell
+ * - Enrique Vidal
+ * - Simone Carletti
+ * - Aaron Patterson
+ * - Esko Lehtme
+ * - Mart Karu
+ * - Nicolás Hock Isaza
+ * - Kevin Valdek
+ * - Zahhar Kirillov
+ * - João Magalhães
+ * - Ingmar
+ * - Illimar Tambek
+ * - Mihkel
+ */
+return [
+ 'year' => ':count aasta|:count aastat',
+ 'y' => ':count a',
+ 'month' => ':count kuu|:count kuud',
+ 'm' => ':count k',
+ 'week' => ':count nädal|:count nädalat',
+ 'w' => ':count näd',
+ 'day' => ':count päev|:count päeva',
+ 'd' => ':count p',
+ 'hour' => ':count tund|:count tundi',
+ 'h' => ':count t',
+ 'minute' => ':count minut|:count minutit',
+ 'min' => ':count min',
+ 'second' => ':count sekund|:count sekundit',
+ 's' => ':count s',
+ 'ago' => ':time tagasi',
+ 'from_now' => ':time pärast',
+ 'after' => ':time pärast',
+ 'before' => ':time enne',
+ 'year_from_now' => ':count aasta',
+ 'month_from_now' => ':count kuu',
+ 'week_from_now' => ':count nädala',
+ 'day_from_now' => ':count päeva',
+ 'hour_from_now' => ':count tunni',
+ 'minute_from_now' => ':count minuti',
+ 'second_from_now' => ':count sekundi',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'diff_now' => 'nüüd',
+ 'diff_today' => 'täna',
+ 'diff_yesterday' => 'eile',
+ 'diff_tomorrow' => 'homme',
+ 'diff_before_yesterday' => 'üleeile',
+ 'diff_after_tomorrow' => 'ülehomme',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[täna] LT',
+ 'nextDay' => '[homme] LT',
+ 'lastDay' => '[eile] LT',
+ 'nextWeek' => 'dddd LT',
+ 'lastWeek' => '[eelmine] dddd LT',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni', 'juuli', 'august', 'september', 'oktoober', 'november', 'detsember'],
+ 'months_short' => ['jaan', 'veebr', 'märts', 'apr', 'mai', 'juuni', 'juuli', 'aug', 'sept', 'okt', 'nov', 'dets'],
+ 'weekdays' => ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev', 'neljapäev', 'reede', 'laupäev'],
+ 'weekdays_short' => ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
+ 'weekdays_min' => ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
+ 'list' => [', ', ' ja '],
+ 'meridiem' => ['enne lõunat', 'pärast lõunat'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/et_EE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/et_EE.php
new file mode 100644
index 0000000..3588f62
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/et_EE.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/et.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/eu.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/eu.php
new file mode 100644
index 0000000..a543f1a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/eu.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - JD Isaacks
+ */
+return [
+ 'year' => 'urte bat|:count urte',
+ 'y' => 'Urte 1|:count urte',
+ 'month' => 'hilabete bat|:count hilabete',
+ 'm' => 'Hile 1|:count hile',
+ 'week' => 'Aste 1|:count aste',
+ 'w' => 'Aste 1|:count aste',
+ 'day' => 'egun bat|:count egun',
+ 'd' => 'Egun 1|:count egun',
+ 'hour' => 'ordu bat|:count ordu',
+ 'h' => 'Ordu 1|:count ordu',
+ 'minute' => 'minutu bat|:count minutu',
+ 'min' => 'Minutu 1|:count minutu',
+ 'second' => 'segundo batzuk|:count segundo',
+ 's' => 'Segundu 1|:count segundu',
+ 'ago' => 'duela :time',
+ 'from_now' => ':time barru',
+ 'after' => ':time geroago',
+ 'before' => ':time lehenago',
+ 'diff_now' => 'orain',
+ 'diff_today' => 'gaur',
+ 'diff_yesterday' => 'atzo',
+ 'diff_tomorrow' => 'bihar',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'YYYY[ko] MMMM[ren] D[a]',
+ 'LLL' => 'YYYY[ko] MMMM[ren] D[a] HH:mm',
+ 'LLLL' => 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[gaur] LT[etan]',
+ 'nextDay' => '[bihar] LT[etan]',
+ 'nextWeek' => 'dddd LT[etan]',
+ 'lastDay' => '[atzo] LT[etan]',
+ 'lastWeek' => '[aurreko] dddd LT[etan]',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['urtarrila', 'otsaila', 'martxoa', 'apirila', 'maiatza', 'ekaina', 'uztaila', 'abuztua', 'iraila', 'urria', 'azaroa', 'abendua'],
+ 'months_short' => ['urt.', 'ots.', 'mar.', 'api.', 'mai.', 'eka.', 'uzt.', 'abu.', 'ira.', 'urr.', 'aza.', 'abe.'],
+ 'weekdays' => ['igandea', 'astelehena', 'asteartea', 'asteazkena', 'osteguna', 'ostirala', 'larunbata'],
+ 'weekdays_short' => ['ig.', 'al.', 'ar.', 'az.', 'og.', 'ol.', 'lr.'],
+ 'weekdays_min' => ['ig', 'al', 'ar', 'az', 'og', 'ol', 'lr'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' eta '],
+ 'meridiem' => ['g', 'a'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/eu_ES.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/eu_ES.php
new file mode 100644
index 0000000..442cca7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/eu_ES.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/eu.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ewo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ewo.php
new file mode 100644
index 0000000..f5ae8cf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ewo.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['kíkíríg', 'ngəgógəle'],
+ 'weekdays' => ['sɔ́ndɔ', 'mɔ́ndi', 'sɔ́ndɔ məlú mə́bɛ̌', 'sɔ́ndɔ məlú mə́lɛ́', 'sɔ́ndɔ məlú mə́nyi', 'fúladé', 'séradé'],
+ 'weekdays_short' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'fúl', 'sér'],
+ 'weekdays_min' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'fúl', 'sér'],
+ 'months' => ['ngɔn osú', 'ngɔn bɛ̌', 'ngɔn lála', 'ngɔn nyina', 'ngɔn tána', 'ngɔn saməna', 'ngɔn zamgbála', 'ngɔn mwom', 'ngɔn ebulú', 'ngɔn awóm', 'ngɔn awóm ai dziá', 'ngɔn awóm ai bɛ̌'],
+ 'months_short' => ['ngo', 'ngb', 'ngl', 'ngn', 'ngt', 'ngs', 'ngz', 'ngm', 'nge', 'nga', 'ngad', 'ngab'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+
+ // Too unreliable
+ /*
+ 'year' => ':count mbu', // less reliable
+ 'y' => ':count mbu', // less reliable
+ 'a_year' => ':count mbu', // less reliable
+
+ 'month' => ':count ngòn', // less reliable
+ 'm' => ':count ngòn', // less reliable
+ 'a_month' => ':count ngòn', // less reliable
+
+ 'week' => ':count mësë', // less reliable
+ 'w' => ':count mësë', // less reliable
+ 'a_week' => ':count mësë', // less reliable
+
+ 'day' => ':count mësë', // less reliable
+ 'd' => ':count mësë', // less reliable
+ 'a_day' => ':count mësë', // less reliable
+
+ 'hour' => ':count awola', // less reliable
+ 'h' => ':count awola', // less reliable
+ 'a_hour' => ':count awola', // less reliable
+
+ 'minute' => ':count awola', // less reliable
+ 'min' => ':count awola', // less reliable
+ 'a_minute' => ':count awola', // less reliable
+ */
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fa.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fa.php
new file mode 100644
index 0000000..72e0308
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fa.php
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - Nasser Ghiasi
+ * - JD Isaacks
+ * - Hossein Jabbari
+ * - nimamo
+ * - hafezdivandari
+ * - Hassan Pezeshk (hpez)
+ */
+return [
+ 'year' => ':count سال',
+ 'a_year' => 'یک سال'.'|:count '.'سال',
+ 'y' => ':count سال',
+ 'month' => ':count ماه',
+ 'a_month' => 'یک ماه'.'|:count '.'ماه',
+ 'm' => ':count ماه',
+ 'week' => ':count هفته',
+ 'a_week' => 'یک هفته'.'|:count '.'هفته',
+ 'w' => ':count هفته',
+ 'day' => ':count روز',
+ 'a_day' => 'یک روز'.'|:count '.'روز',
+ 'd' => ':count روز',
+ 'hour' => ':count ساعت',
+ 'a_hour' => 'یک ساعت'.'|:count '.'ساعت',
+ 'h' => ':count ساعت',
+ 'minute' => ':count دقیقه',
+ 'a_minute' => 'یک دقیقه'.'|:count '.'دقیقه',
+ 'min' => ':count دقیقه',
+ 'second' => ':count ثانیه',
+ 's' => ':count ثانیه',
+ 'ago' => ':time پیش',
+ 'from_now' => ':time دیگر',
+ 'after' => ':time پس از',
+ 'before' => ':time پیش از',
+ 'diff_now' => 'اکنون',
+ 'diff_today' => 'امروز',
+ 'diff_today_regexp' => 'امروز(?:\\s+ساعت)?',
+ 'diff_yesterday' => 'دیروز',
+ 'diff_yesterday_regexp' => 'دیروز(?:\\s+ساعت)?',
+ 'diff_tomorrow' => 'فردا',
+ 'diff_tomorrow_regexp' => 'فردا(?:\\s+ساعت)?',
+ 'formats' => [
+ 'LT' => 'OH:Om',
+ 'LTS' => 'OH:Om:Os',
+ 'L' => 'OD/OM/OY',
+ 'LL' => 'OD MMMM OY',
+ 'LLL' => 'OD MMMM OY OH:Om',
+ 'LLLL' => 'dddd, OD MMMM OY OH:Om',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[امروز ساعت] LT',
+ 'nextDay' => '[فردا ساعت] LT',
+ 'nextWeek' => 'dddd [ساعت] LT',
+ 'lastDay' => '[دیروز ساعت] LT',
+ 'lastWeek' => 'dddd [پیش] [ساعت] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':timeم',
+ 'meridiem' => ['قبل از ظهر', 'بعد از ظهر'],
+ 'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
+ 'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
+ 'weekdays' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
+ 'weekdays_short' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
+ 'weekdays_min' => ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => ['، ', ' و '],
+ 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰۴', '۰۵', '۰۶', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱۴', '۱۵', '۱۶', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲۴', '۲۵', '۲۶', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳۴', '۳۵', '۳۶', '۳۷', '۳۸', '۳۹', '۴۰', '۴۱', '۴۲', '۴۳', '۴۴', '۴۵', '۴۶', '۴۷', '۴۸', '۴۹', '۵۰', '۵۱', '۵۲', '۵۳', '۵۴', '۵۵', '۵۶', '۵۷', '۵۸', '۵۹', '۶۰', '۶۱', '۶۲', '۶۳', '۶۴', '۶۵', '۶۶', '۶۷', '۶۸', '۶۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷۴', '۷۵', '۷۶', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸۴', '۸۵', '۸۶', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹۴', '۹۵', '۹۶', '۹۷', '۹۸', '۹۹'],
+ 'months_short_standalone' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
+ 'weekend' => [5, 5],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fa_AF.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fa_AF.php
new file mode 100644
index 0000000..06566fa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fa_AF.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fa.php', [
+ 'meridiem' => ['ق', 'ب'],
+ 'weekend' => [4, 5],
+ 'formats' => [
+ 'L' => 'OY/OM/OD',
+ 'LL' => 'OD MMM OY',
+ 'LLL' => 'OD MMMM OY، H:mm',
+ 'LLLL' => 'dddd OD MMMM OY، H:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fa_IR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fa_IR.php
new file mode 100644
index 0000000..6d1832c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fa_IR.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fa.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff.php
new file mode 100644
index 0000000..9525c95
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'months' => ['siilo', 'colte', 'mbooy', 'seeɗto', 'duujal', 'korse', 'morso', 'juko', 'siilto', 'yarkomaa', 'jolal', 'bowte'],
+ 'months_short' => ['sii', 'col', 'mbo', 'see', 'duu', 'kor', 'mor', 'juk', 'slt', 'yar', 'jol', 'bow'],
+ 'weekdays' => ['dewo', 'aaɓnde', 'mawbaare', 'njeslaare', 'naasaande', 'mawnde', 'hoore-biir'],
+ 'weekdays_short' => ['dew', 'aaɓ', 'maw', 'nje', 'naa', 'mwd', 'hbi'],
+ 'weekdays_min' => ['dew', 'aaɓ', 'maw', 'nje', 'naa', 'mwd', 'hbi'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['subaka', 'kikiiɗe'],
+
+ 'year' => ':count baret', // less reliable
+ 'y' => ':count baret', // less reliable
+ 'a_year' => ':count baret', // less reliable
+
+ 'month' => ':count lewru', // less reliable
+ 'm' => ':count lewru', // less reliable
+ 'a_month' => ':count lewru', // less reliable
+
+ 'week' => ':count naange', // less reliable
+ 'w' => ':count naange', // less reliable
+ 'a_week' => ':count naange', // less reliable
+
+ 'day' => ':count dian', // less reliable
+ 'd' => ':count dian', // less reliable
+ 'a_day' => ':count dian', // less reliable
+
+ 'hour' => ':count montor', // less reliable
+ 'h' => ':count montor', // less reliable
+ 'a_hour' => ':count montor', // less reliable
+
+ 'minute' => ':count tokossuoum', // less reliable
+ 'min' => ':count tokossuoum', // less reliable
+ 'a_minute' => ':count tokossuoum', // less reliable
+
+ 'second' => ':count tenen', // less reliable
+ 's' => ':count tenen', // less reliable
+ 'a_second' => ':count tenen', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_CM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_CM.php
new file mode 100644
index 0000000..dafa98e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_CM.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ff.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_GN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_GN.php
new file mode 100644
index 0000000..dafa98e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_GN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ff.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_MR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_MR.php
new file mode 100644
index 0000000..65276d3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_MR.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ff.php', [
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd D MMMM YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_SN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_SN.php
new file mode 100644
index 0000000..1e4c8b6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ff_SN.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Pular-Fulfulde.org Ibrahima Sarr admin@pulaar-fulfulde.org
+ */
+return require __DIR__.'/ff.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fi.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fi.php
new file mode 100644
index 0000000..2003e1e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fi.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - Janne Warén
+ * - digitalfrost
+ * - Tsutomu Kuroda
+ * - Roope Salmi
+ * - tjku
+ * - Max Melentiev
+ * - Sami Haahtinen
+ * - Teemu Leisti
+ * - Artem Ignatyev
+ * - Akira Matsuda
+ * - Christopher Dell
+ * - Enrique Vidal
+ * - Simone Carletti
+ * - Robert Bjarnason
+ * - Aaron Patterson
+ * - Nicolás Hock Isaza
+ * - Tom Hughes
+ * - Sven Fuchs
+ * - Petri Kivikangas
+ * - Nizar Jouini
+ * - Marko Seppae
+ * - Tomi Mynttinen (Pikseli)
+ * - Petteri (powergrip)
+ */
+return [
+ 'year' => ':count vuosi|:count vuotta',
+ 'y' => ':count v',
+ 'month' => ':count kuukausi|:count kuukautta',
+ 'm' => ':count kk',
+ 'week' => ':count viikko|:count viikkoa',
+ 'w' => ':count vk',
+ 'day' => ':count päivä|:count päivää',
+ 'd' => ':count pv',
+ 'hour' => ':count tunti|:count tuntia',
+ 'h' => ':count t',
+ 'minute' => ':count minuutti|:count minuuttia',
+ 'min' => ':count min',
+ 'second' => ':count sekunti|:count sekuntia',
+ 'a_second' => 'muutama sekunti|:count sekuntia',
+ 's' => ':count s',
+ 'ago' => ':time sitten',
+ 'from_now' => ':time päästä',
+ 'year_from_now' => ':count vuoden',
+ 'month_from_now' => ':count kuukauden',
+ 'week_from_now' => ':count viikon',
+ 'day_from_now' => ':count päivän',
+ 'hour_from_now' => ':count tunnin',
+ 'minute_from_now' => ':count minuutin',
+ 'second_from_now' => ':count sekunnin',
+ 'after' => ':time sen jälkeen',
+ 'before' => ':time ennen',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' ja '],
+ 'diff_now' => 'nyt',
+ 'diff_yesterday' => 'eilen',
+ 'diff_tomorrow' => 'huomenna',
+ 'formats' => [
+ 'LT' => 'HH.mm',
+ 'LTS' => 'HH.mm:ss',
+ 'L' => 'D.M.YYYY',
+ 'LL' => 'dddd D. MMMM[ta] YYYY',
+ 'LLL' => 'D.MM. HH.mm',
+ 'LLLL' => 'D. MMMM[ta] YYYY HH.mm',
+ ],
+ 'weekdays' => ['sunnuntai', 'maanantai', 'tiistai', 'keskiviikko', 'torstai', 'perjantai', 'lauantai'],
+ 'weekdays_short' => ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
+ 'weekdays_min' => ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
+ 'months' => ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'],
+ 'months_short' => ['tammi', 'helmi', 'maalis', 'huhti', 'touko', 'kesä', 'heinä', 'elo', 'syys', 'loka', 'marras', 'joulu'],
+ 'meridiem' => ['aamupäivä', 'iltapäivä'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fi_FI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fi_FI.php
new file mode 100644
index 0000000..3597fa2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fi_FI.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fi.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fil.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fil.php
new file mode 100644
index 0000000..61114e3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fil.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/fil_PH.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fil_PH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fil_PH.php
new file mode 100644
index 0000000..bcf1580
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fil_PH.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Rene Torres Rene Torres, Pablo Saratxaga rgtorre@rocketmail.com, pablo@mandrakesoft.com
+ * - Jaycee Mariano (alohajaycee)
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'MM/DD/YY',
+ ],
+ 'months' => ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
+ 'months_short' => ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set', 'Okt', 'Nob', 'Dis'],
+ 'weekdays' => ['Linggo', 'Lunes', 'Martes', 'Miyerkoles', 'Huwebes', 'Biyernes', 'Sabado'],
+ 'weekdays_short' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
+ 'weekdays_min' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['N.U.', 'N.H.'],
+
+ 'before' => ':time bago',
+ 'after' => ':time pagkatapos',
+
+ 'year' => ':count taon',
+ 'y' => ':count taon',
+ 'a_year' => ':count taon',
+
+ 'month' => ':count buwan',
+ 'm' => ':count buwan',
+ 'a_month' => ':count buwan',
+
+ 'week' => ':count linggo',
+ 'w' => ':count linggo',
+ 'a_week' => ':count linggo',
+
+ 'day' => ':count araw',
+ 'd' => ':count araw',
+ 'a_day' => ':count araw',
+
+ 'hour' => ':count oras',
+ 'h' => ':count oras',
+ 'a_hour' => ':count oras',
+
+ 'minute' => ':count minuto',
+ 'min' => ':count minuto',
+ 'a_minute' => ':count minuto',
+
+ 'second' => ':count segundo',
+ 's' => ':count segundo',
+ 'a_second' => ':count segundo',
+
+ 'ago' => ':time ang nakalipas',
+ 'from_now' => 'sa :time',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fo.php
new file mode 100644
index 0000000..6a14a6f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fo.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kristian Sakarisson
+ * - François B
+ * - JD Isaacks
+ * - Sverri Mohr Olsen
+ */
+return [
+ 'year' => 'eitt ár|:count ár',
+ 'y' => ':count ár|:count ár',
+ 'month' => 'ein mánaði|:count mánaðir',
+ 'm' => ':count mánaður|:count mánaðir',
+ 'week' => ':count vika|:count vikur',
+ 'w' => ':count vika|:count vikur',
+ 'day' => 'ein dagur|:count dagar',
+ 'd' => ':count dag|:count dagar',
+ 'hour' => 'ein tími|:count tímar',
+ 'h' => ':count tími|:count tímar',
+ 'minute' => 'ein minutt|:count minuttir',
+ 'min' => ':count minutt|:count minuttir',
+ 'second' => 'fá sekund|:count sekundir',
+ 's' => ':count sekund|:count sekundir',
+ 'ago' => ':time síðani',
+ 'from_now' => 'um :time',
+ 'after' => ':time aftaná',
+ 'before' => ':time áðrenn',
+ 'diff_today' => 'Í',
+ 'diff_yesterday' => 'Í',
+ 'diff_yesterday_regexp' => 'Í(?:\\s+gjár)?(?:\\s+kl.)?',
+ 'diff_tomorrow' => 'Í',
+ 'diff_tomorrow_regexp' => 'Í(?:\\s+morgin)?(?:\\s+kl.)?',
+ 'diff_today_regexp' => 'Í(?:\\s+dag)?(?:\\s+kl.)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D. MMMM, YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Í dag kl.] LT',
+ 'nextDay' => '[Í morgin kl.] LT',
+ 'nextWeek' => 'dddd [kl.] LT',
+ 'lastDay' => '[Í gjár kl.] LT',
+ 'lastWeek' => '[síðstu] dddd [kl] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['januar', 'februar', 'mars', 'apríl', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
+ 'weekdays' => ['sunnudagur', 'mánadagur', 'týsdagur', 'mikudagur', 'hósdagur', 'fríggjadagur', 'leygardagur'],
+ 'weekdays_short' => ['sun', 'mán', 'týs', 'mik', 'hós', 'frí', 'ley'],
+ 'weekdays_min' => ['su', 'má', 'tý', 'mi', 'hó', 'fr', 'le'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' og '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fo_DK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fo_DK.php
new file mode 100644
index 0000000..e0f4537
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fo_DK.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fo.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.yy',
+ 'LL' => 'DD.MM.YYYY',
+ 'LLL' => 'D. MMMM YYYY, HH:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY, HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fo_FO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fo_FO.php
new file mode 100644
index 0000000..6a4bc31
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fo_FO.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fo.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr.php
new file mode 100644
index 0000000..73fe5e4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Dieter Sting
+ * - François B
+ * - Maxime VALY
+ * - JD Isaacks
+ * - Dieter Sting
+ * - François B
+ * - JD Isaacks
+ * - Sebastian Thierer
+ * - Fastfuel
+ * - Pete Scopes (pdscopes)
+ */
+return [
+ 'year' => ':count an|:count ans',
+ 'a_year' => 'un an|:count ans',
+ 'y' => ':count an|:count ans',
+ 'month' => ':count mois|:count mois',
+ 'a_month' => 'un mois|:count mois',
+ 'm' => ':count mois',
+ 'week' => ':count semaine|:count semaines',
+ 'a_week' => 'une semaine|:count semaines',
+ 'w' => ':count sem.',
+ 'day' => ':count jour|:count jours',
+ 'a_day' => 'un jour|:count jours',
+ 'd' => ':count j',
+ 'hour' => ':count heure|:count heures',
+ 'a_hour' => 'une heure|:count heures',
+ 'h' => ':count h',
+ 'minute' => ':count minute|:count minutes',
+ 'a_minute' => 'une minute|:count minutes',
+ 'min' => ':count min',
+ 'second' => ':count seconde|:count secondes',
+ 'a_second' => 'quelques secondes|:count secondes',
+ 's' => ':count s',
+ 'millisecond' => ':count milliseconde|:count millisecondes',
+ 'a_millisecond' => 'une milliseconde|:count millisecondes',
+ 'ms' => ':countms',
+ 'microsecond' => ':count microseconde|:count microsecondes',
+ 'a_microsecond' => 'une microseconde|:count microsecondes',
+ 'µs' => ':countµs',
+ 'ago' => 'il y a :time',
+ 'from_now' => 'dans :time',
+ 'after' => ':time après',
+ 'before' => ':time avant',
+ 'diff_now' => "à l'instant",
+ 'diff_today' => "aujourd'hui",
+ 'diff_today_regexp' => "aujourd'hui(?:\s+à)?",
+ 'diff_yesterday' => 'hier',
+ 'diff_yesterday_regexp' => 'hier(?:\s+à)?',
+ 'diff_tomorrow' => 'demain',
+ 'diff_tomorrow_regexp' => 'demain(?:\s+à)?',
+ 'diff_before_yesterday' => 'avant-hier',
+ 'diff_after_tomorrow' => 'après-demain',
+ 'period_recurrences' => ':count fois',
+ 'period_interval' => 'tous les :interval',
+ 'period_start_date' => 'de :date',
+ 'period_end_date' => 'à :date',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Aujourd’hui à] LT',
+ 'nextDay' => '[Demain à] LT',
+ 'nextWeek' => 'dddd [à] LT',
+ 'lastDay' => '[Hier à] LT',
+ 'lastWeek' => 'dddd [dernier à] LT',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],
+ 'months_short' => ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'],
+ 'weekdays' => ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
+ 'weekdays_short' => ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
+ 'weekdays_min' => ['di', 'lu', 'ma', 'me', 'je', 've', 'sa'],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ // In french, only the first has be ordinal, other number remains cardinal
+ // @link https://fr.wikihow.com/%C3%A9crire-la-date-en-fran%C3%A7ais
+ case 'D':
+ return $number.($number === 1 ? 'er' : '');
+
+ default:
+ case 'M':
+ case 'Q':
+ case 'DDD':
+ case 'd':
+ return $number.($number === 1 ? 'er' : 'e');
+
+ // Words with feminine grammatical gender: semaine
+ case 'w':
+ case 'W':
+ return $number.($number === 1 ? 're' : 'e');
+ }
+ },
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' et '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BE.php
new file mode 100644
index 0000000..f6cafe8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BE.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'months_short' => ['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jui', 'aoû', 'sep', 'oct', 'nov', 'déc'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BF.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BF.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BF.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BI.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BI.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BJ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BJ.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BJ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BL.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_BL.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CA.php
new file mode 100644
index 0000000..c9f6346
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CA.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Dieter Sting
+ * - François B
+ * - Maxime VALY
+ * - JD Isaacks
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'formats' => [
+ 'L' => 'YYYY-MM-DD',
+ ],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CD.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CD.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CF.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CF.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CF.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CG.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CG.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CH.php
new file mode 100644
index 0000000..8674c27
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CH.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Dieter Sting
+ * - François B
+ * - Gaspard Bucher
+ * - Maxime VALY
+ * - JD Isaacks
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CI.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CI.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CM.php
new file mode 100644
index 0000000..52b951c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_CM.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'meridiem' => ['mat.', 'soir'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_DJ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_DJ.php
new file mode 100644
index 0000000..40579a4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_DJ.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'first_day_of_week' => 6,
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd D MMMM YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_DZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_DZ.php
new file mode 100644
index 0000000..2c1ab85
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_DZ.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'first_day_of_week' => 6,
+ 'weekend' => [5, 6],
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd D MMMM YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_FR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_FR.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_FR.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GA.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GA.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GF.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GF.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GF.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GN.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GP.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GP.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GP.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GQ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GQ.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_GQ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_HT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_HT.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_HT.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_KM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_KM.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_KM.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_LU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_LU.php
new file mode 100644
index 0000000..8e37d85
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_LU.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months_short' => ['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jui', 'aoû', 'sep', 'oct', 'nov', 'déc'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MA.php
new file mode 100644
index 0000000..7d2b1db
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MA.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'first_day_of_week' => 6,
+ 'weekend' => [5, 6],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MC.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MC.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MF.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MF.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MF.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MG.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MG.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_ML.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_ML.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_ML.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MQ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MQ.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MQ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MR.php
new file mode 100644
index 0000000..d177a7d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MR.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd D MMMM YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MU.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_MU.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_NC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_NC.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_NC.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_NE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_NE.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_NE.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_PF.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_PF.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_PF.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_PM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_PM.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_PM.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_RE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_RE.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_RE.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_RW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_RW.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_RW.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_SC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_SC.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_SC.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_SN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_SN.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_SN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_SY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_SY.php
new file mode 100644
index 0000000..2c1ab85
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_SY.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'first_day_of_week' => 6,
+ 'weekend' => [5, 6],
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd D MMMM YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_TD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_TD.php
new file mode 100644
index 0000000..d177a7d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_TD.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd D MMMM YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_TG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_TG.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_TG.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_TN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_TN.php
new file mode 100644
index 0000000..d3e2656
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_TN.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'weekend' => [5, 6],
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd D MMMM YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_VU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_VU.php
new file mode 100644
index 0000000..d177a7d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_VU.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fr.php', [
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd D MMMM YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_WF.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_WF.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_WF.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_YT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_YT.php
new file mode 100644
index 0000000..f9801e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fr_YT.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/fr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fur.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fur.php
new file mode 100644
index 0000000..36c2564
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fur.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/fur_IT.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fur_IT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fur_IT.php
new file mode 100644
index 0000000..0147a59
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fur_IT.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Pablo Saratxaga pablo@mandrakesoft.com
+ */
+return [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD. MM. YY',
+ 'LL' => 'DD di MMMM dal YYYY',
+ 'LLL' => 'DD di MMM HH:mm',
+ 'LLLL' => 'DD di MMMM dal YYYY HH:mm',
+ ],
+ 'months' => ['zenâr', 'fevrâr', 'març', 'avrîl', 'mai', 'jugn', 'lui', 'avost', 'setembar', 'otubar', 'novembar', 'dicembar'],
+ 'months_short' => ['zen', 'fev', 'mar', 'avr', 'mai', 'jug', 'lui', 'avo', 'set', 'otu', 'nov', 'dic'],
+ 'weekdays' => ['domenie', 'lunis', 'martars', 'miercus', 'joibe', 'vinars', 'sabide'],
+ 'weekdays_short' => ['dom', 'lun', 'mar', 'mie', 'joi', 'vin', 'sab'],
+ 'weekdays_min' => ['dom', 'lun', 'mar', 'mie', 'joi', 'vin', 'sab'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'year' => ':count an',
+ 'month' => ':count mês',
+ 'week' => ':count setemane',
+ 'day' => ':count zornade',
+ 'hour' => ':count ore',
+ 'minute' => ':count minût',
+ 'second' => ':count secont',
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fy.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fy.php
new file mode 100644
index 0000000..c1b5439
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fy.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Tim Fish
+ * - JD Isaacks
+ */
+return [
+ 'year' => ':count jier|:count jierren',
+ 'a_year' => 'ien jier|:count jierren',
+ 'y' => ':count j',
+ 'month' => ':count moanne|:count moannen',
+ 'a_month' => 'ien moanne|:count moannen',
+ 'm' => ':count moa.',
+ 'week' => ':count wike|:count wiken',
+ 'a_week' => 'in wike|:count wiken',
+ 'a' => ':count w.',
+ 'day' => ':count dei|:count dagen',
+ 'a_day' => 'ien dei|:count dagen',
+ 'd' => ':count d.',
+ 'hour' => ':count oere|:count oeren',
+ 'a_hour' => 'ien oere|:count oeren',
+ 'h' => ':count o.',
+ 'minute' => ':count minút|:count minuten',
+ 'a_minute' => 'ien minút|:count minuten',
+ 'min' => ':count min.',
+ 'second' => ':count sekonde|:count sekonden',
+ 'a_second' => 'in pear sekonden|:count sekonden',
+ 's' => ':count s.',
+ 'ago' => ':time lyn',
+ 'from_now' => 'oer :time',
+ 'diff_yesterday' => 'juster',
+ 'diff_yesterday_regexp' => 'juster(?:\\s+om)?',
+ 'diff_today' => 'hjoed',
+ 'diff_today_regexp' => 'hjoed(?:\\s+om)?',
+ 'diff_tomorrow' => 'moarn',
+ 'diff_tomorrow_regexp' => 'moarn(?:\\s+om)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD-MM-YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[hjoed om] LT',
+ 'nextDay' => '[moarn om] LT',
+ 'nextWeek' => 'dddd [om] LT',
+ 'lastDay' => '[juster om] LT',
+ 'lastWeek' => '[ôfrûne] dddd [om] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de');
+ },
+ 'months' => ['jannewaris', 'febrewaris', 'maart', 'april', 'maaie', 'juny', 'july', 'augustus', 'septimber', 'oktober', 'novimber', 'desimber'],
+ 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
+ 'mmm_suffix' => '.',
+ 'weekdays' => ['snein', 'moandei', 'tiisdei', 'woansdei', 'tongersdei', 'freed', 'sneon'],
+ 'weekdays_short' => ['si.', 'mo.', 'ti.', 'wo.', 'to.', 'fr.', 'so.'],
+ 'weekdays_min' => ['Si', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'So'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' en '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fy_DE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fy_DE.php
new file mode 100644
index 0000000..8559d5c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fy_DE.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandriva.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['Jaunuwoa', 'Februwoa', 'Moaz', 'Aprell', 'Mai', 'Juni', 'Juli', 'August', 'Septamba', 'Oktoba', 'Nowamba', 'Dezamba'],
+ 'months_short' => ['Jan', 'Feb', 'Moz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Now', 'Dez'],
+ 'weekdays' => ['Sinndag', 'Mondag', 'Dingsdag', 'Meddwäakj', 'Donnadag', 'Friedag', 'Sinnowend'],
+ 'weekdays_short' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
+ 'weekdays_min' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fy_NL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fy_NL.php
new file mode 100644
index 0000000..01cc96c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/fy_NL.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/fy.php', [
+ 'formats' => [
+ 'L' => 'DD-MM-YY',
+ ],
+ 'months' => ['Jannewaris', 'Febrewaris', 'Maart', 'April', 'Maaie', 'Juny', 'July', 'Augustus', 'Septimber', 'Oktober', 'Novimber', 'Desimber'],
+ 'months_short' => ['Jan', 'Feb', 'Mrt', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'weekdays' => ['Snein', 'Moandei', 'Tiisdei', 'Woansdei', 'Tongersdei', 'Freed', 'Sneon'],
+ 'weekdays_short' => ['Sn', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'Sn'],
+ 'weekdays_min' => ['Sn', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'Sn'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ga.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ga.php
new file mode 100644
index 0000000..9f07a26
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ga.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Thanks to André Silva : https://github.com/askpt
+ */
+
+return [
+ 'year' => ':count bliain',
+ 'a_year' => '{1}bliain|:count bliain',
+ 'y' => ':countb',
+ 'month' => ':count mí',
+ 'a_month' => '{1}mí|:count mí',
+ 'm' => ':countm',
+ 'week' => ':count sheachtain',
+ 'a_week' => '{1}sheachtain|:count sheachtain',
+ 'w' => ':countsh',
+ 'day' => ':count lá',
+ 'a_day' => '{1}lá|:count lá',
+ 'd' => ':countl',
+ 'hour' => ':count uair an chloig',
+ 'a_hour' => '{1}uair an chloig|:count uair an chloig',
+ 'h' => ':countu',
+ 'minute' => ':count nóiméad',
+ 'a_minute' => '{1}nóiméad|:count nóiméad',
+ 'min' => ':countn',
+ 'second' => ':count soicind',
+ 'a_second' => '{1}cúpla soicind|:count soicind',
+ 's' => ':countso',
+ 'ago' => ':time ó shin',
+ 'from_now' => 'i :time',
+ 'after' => ':time tar éis',
+ 'before' => ':time roimh',
+ 'diff_now' => 'anois',
+ 'diff_today' => 'Inniu',
+ 'diff_today_regexp' => 'Inniu(?:\\s+ag)?',
+ 'diff_yesterday' => 'inné',
+ 'diff_yesterday_regexp' => 'Inné(?:\\s+aig)?',
+ 'diff_tomorrow' => 'amárach',
+ 'diff_tomorrow_regexp' => 'Amárach(?:\\s+ag)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Inniu ag] LT',
+ 'nextDay' => '[Amárach ag] LT',
+ 'nextWeek' => 'dddd [ag] LT',
+ 'lastDay' => '[Inné aig] LT',
+ 'lastWeek' => 'dddd [seo caite] [ag] LT',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['Eanáir', 'Feabhra', 'Márta', 'Aibreán', 'Bealtaine', 'Méitheamh', 'Iúil', 'Lúnasa', 'Meán Fómhair', 'Deaireadh Fómhair', 'Samhain', 'Nollaig'],
+ 'months_short' => ['Eaná', 'Feab', 'Márt', 'Aibr', 'Beal', 'Méit', 'Iúil', 'Lúna', 'Meán', 'Deai', 'Samh', 'Noll'],
+ 'weekdays' => ['Dé Domhnaigh', 'Dé Luain', 'Dé Máirt', 'Dé Céadaoin', 'Déardaoin', 'Dé hAoine', 'Dé Satharn'],
+ 'weekdays_short' => ['Dom', 'Lua', 'Mái', 'Céa', 'Déa', 'hAo', 'Sat'],
+ 'weekdays_min' => ['Do', 'Lu', 'Má', 'Ce', 'Dé', 'hA', 'Sa'],
+ 'ordinal' => function ($number) {
+ return $number.($number === 1 ? 'd' : ($number % 10 === 2 ? 'na' : 'mh'));
+ },
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' agus '],
+ 'meridiem' => ['r.n.', 'i.n.'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ga_IE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ga_IE.php
new file mode 100644
index 0000000..d50630c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ga_IE.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ga.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gd.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gd.php
new file mode 100644
index 0000000..63d064d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gd.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Jon Ashdown
+ */
+return [
+ 'year' => ':count bliadhna',
+ 'a_year' => '{1}bliadhna|:count bliadhna',
+ 'y' => ':count b.',
+ 'month' => ':count mìosan',
+ 'a_month' => '{1}mìos|:count mìosan',
+ 'm' => ':count ms.',
+ 'week' => ':count seachdainean',
+ 'a_week' => '{1}seachdain|:count seachdainean',
+ 'w' => ':count s.',
+ 'day' => ':count latha',
+ 'a_day' => '{1}latha|:count latha',
+ 'd' => ':count l.',
+ 'hour' => ':count uairean',
+ 'a_hour' => '{1}uair|:count uairean',
+ 'h' => ':count u.',
+ 'minute' => ':count mionaidean',
+ 'a_minute' => '{1}mionaid|:count mionaidean',
+ 'min' => ':count md.',
+ 'second' => ':count diogan',
+ 'a_second' => '{1}beagan diogan|:count diogan',
+ 's' => ':count d.',
+ 'ago' => 'bho chionn :time',
+ 'from_now' => 'ann an :time',
+ 'diff_yesterday' => 'An-dè',
+ 'diff_yesterday_regexp' => 'An-dè(?:\\s+aig)?',
+ 'diff_today' => 'An-diugh',
+ 'diff_today_regexp' => 'An-diugh(?:\\s+aig)?',
+ 'diff_tomorrow' => 'A-màireach',
+ 'diff_tomorrow_regexp' => 'A-màireach(?:\\s+aig)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[An-diugh aig] LT',
+ 'nextDay' => '[A-màireach aig] LT',
+ 'nextWeek' => 'dddd [aig] LT',
+ 'lastDay' => '[An-dè aig] LT',
+ 'lastWeek' => 'dddd [seo chaidh] [aig] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ return $number.($number === 1 ? 'd' : ($number % 10 === 2 ? 'na' : 'mh'));
+ },
+ 'months' => ['Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd'],
+ 'months_short' => ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'],
+ 'weekdays' => ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'],
+ 'weekdays_short' => ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'],
+ 'weekdays_min' => ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' agus '],
+ 'meridiem' => ['m', 'f'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gd_GB.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gd_GB.php
new file mode 100644
index 0000000..80da9c6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gd_GB.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/gd.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gez.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gez.php
new file mode 100644
index 0000000..b8a2f0e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gez.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/gez_ER.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gez_ER.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gez_ER.php
new file mode 100644
index 0000000..f19d1df
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gez_ER.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['ጠሐረ', 'ከተተ', 'መገበ', 'አኀዘ', 'ግንባት', 'ሠንየ', 'ሐመለ', 'ነሐሰ', 'ከረመ', 'ጠቀመ', 'ኀደረ', 'ኀሠሠ'],
+ 'months_short' => ['ጠሐረ', 'ከተተ', 'መገበ', 'አኀዘ', 'ግንባ', 'ሠንየ', 'ሐመለ', 'ነሐሰ', 'ከረመ', 'ጠቀመ', 'ኀደረ', 'ኀሠሠ'],
+ 'weekdays' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚት'],
+ 'weekdays_short' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
+ 'weekdays_min' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ጽባሕ', 'ምሴት'],
+
+ 'month' => ':count ወርሕ', // less reliable
+ 'm' => ':count ወርሕ', // less reliable
+ 'a_month' => ':count ወርሕ', // less reliable
+
+ 'week' => ':count ሰብዑ', // less reliable
+ 'w' => ':count ሰብዑ', // less reliable
+ 'a_week' => ':count ሰብዑ', // less reliable
+
+ 'hour' => ':count አንትሙ', // less reliable
+ 'h' => ':count አንትሙ', // less reliable
+ 'a_hour' => ':count አንትሙ', // less reliable
+
+ 'minute' => ':count ንኡስ', // less reliable
+ 'min' => ':count ንኡስ', // less reliable
+ 'a_minute' => ':count ንኡስ', // less reliable
+
+ 'year' => ':count ዓመት',
+ 'y' => ':count ዓመት',
+ 'a_year' => ':count ዓመት',
+
+ 'day' => ':count ዕለት',
+ 'd' => ':count ዕለት',
+ 'a_day' => ':count ዕለት',
+
+ 'second' => ':count ካልእ',
+ 's' => ':count ካልእ',
+ 'a_second' => ':count ካልእ',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gez_ET.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gez_ET.php
new file mode 100644
index 0000000..3933009
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gez_ET.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'],
+ 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
+ 'weekdays' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚት'],
+ 'weekdays_short' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
+ 'weekdays_min' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ጽባሕ', 'ምሴት'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gl.php
new file mode 100644
index 0000000..58c1db1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gl.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Fidel Pita
+ * - JD Isaacks
+ * - Diego Vilariño
+ * - Sebastian Thierer
+ */
+return [
+ 'year' => ':count ano|:count anos',
+ 'a_year' => 'un ano|:count anos',
+ 'y' => ':count a.',
+ 'month' => ':count mes|:count meses',
+ 'a_month' => 'un mes|:count meses',
+ 'm' => ':count mes.',
+ 'week' => ':count semana|:count semanas',
+ 'a_week' => 'unha semana|:count semanas',
+ 'w' => ':count sem.',
+ 'day' => ':count día|:count días',
+ 'a_day' => 'un día|:count días',
+ 'd' => ':count d.',
+ 'hour' => ':count hora|:count horas',
+ 'a_hour' => 'unha hora|:count horas',
+ 'h' => ':count h.',
+ 'minute' => ':count minuto|:count minutos',
+ 'a_minute' => 'un minuto|:count minutos',
+ 'min' => ':count min.',
+ 'second' => ':count segundo|:count segundos',
+ 'a_second' => 'uns segundos|:count segundos',
+ 's' => ':count seg.',
+ 'ago' => 'hai :time',
+ 'from_now' => function ($time) {
+ if (str_starts_with($time, 'un')) {
+ return "n$time";
+ }
+
+ return "en $time";
+ },
+ 'diff_now' => 'agora',
+ 'diff_today' => 'hoxe',
+ 'diff_today_regexp' => 'hoxe(?:\\s+ás)?',
+ 'diff_yesterday' => 'onte',
+ 'diff_yesterday_regexp' => 'onte(?:\\s+á)?',
+ 'diff_tomorrow' => 'mañá',
+ 'diff_tomorrow_regexp' => 'mañá(?:\\s+ás)?',
+ 'after' => ':time despois',
+ 'before' => ':time antes',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D [de] MMMM [de] YYYY',
+ 'LLL' => 'D [de] MMMM [de] YYYY H:mm',
+ 'LLLL' => 'dddd, D [de] MMMM [de] YYYY H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => function (\Carbon\CarbonInterface $current) {
+ return '[hoxe '.($current->hour !== 1 ? 'ás' : 'á').'] LT';
+ },
+ 'nextDay' => function (\Carbon\CarbonInterface $current) {
+ return '[mañá '.($current->hour !== 1 ? 'ás' : 'á').'] LT';
+ },
+ 'nextWeek' => function (\Carbon\CarbonInterface $current) {
+ return 'dddd ['.($current->hour !== 1 ? 'ás' : 'á').'] LT';
+ },
+ 'lastDay' => function (\Carbon\CarbonInterface $current) {
+ return '[onte '.($current->hour !== 1 ? 'á' : 'a').'] LT';
+ },
+ 'lastWeek' => function (\Carbon\CarbonInterface $current) {
+ return '[o] dddd [pasado '.($current->hour !== 1 ? 'ás' : 'á').'] LT';
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numberº',
+ 'months' => ['xaneiro', 'febreiro', 'marzo', 'abril', 'maio', 'xuño', 'xullo', 'agosto', 'setembro', 'outubro', 'novembro', 'decembro'],
+ 'months_short' => ['xan.', 'feb.', 'mar.', 'abr.', 'mai.', 'xuñ.', 'xul.', 'ago.', 'set.', 'out.', 'nov.', 'dec.'],
+ 'weekdays' => ['domingo', 'luns', 'martes', 'mércores', 'xoves', 'venres', 'sábado'],
+ 'weekdays_short' => ['dom.', 'lun.', 'mar.', 'mér.', 'xov.', 'ven.', 'sáb.'],
+ 'weekdays_min' => ['do', 'lu', 'ma', 'mé', 'xo', 've', 'sá'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' e '],
+ 'meridiem' => ['a.m.', 'p.m.'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gl_ES.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gl_ES.php
new file mode 100644
index 0000000..12a565f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gl_ES.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/gl.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gom.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gom.php
new file mode 100644
index 0000000..2a0584f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gom.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/gom_Latn.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gom_Latn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gom_Latn.php
new file mode 100644
index 0000000..5e54a36
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gom_Latn.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return [
+ 'year' => ':count voros|:count vorsam',
+ 'y' => ':countv',
+ 'month' => ':count mhoino|:count mhoine',
+ 'm' => ':countmh',
+ 'week' => ':count satolleacho|:count satolleache',
+ 'w' => ':countsa|:countsa',
+ 'day' => ':count dis',
+ 'd' => ':countd',
+ 'hour' => ':count hor|:count horam',
+ 'h' => ':counth',
+ 'minute' => ':count minute|:count mintam',
+ 'min' => ':countm',
+ 'second' => ':count second',
+ 's' => ':counts',
+
+ 'diff_today' => 'Aiz',
+ 'diff_yesterday' => 'Kal',
+ 'diff_tomorrow' => 'Faleam',
+ 'formats' => [
+ 'LT' => 'A h:mm [vazta]',
+ 'LTS' => 'A h:mm:ss [vazta]',
+ 'L' => 'DD-MM-YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY A h:mm [vazta]',
+ 'LLLL' => 'dddd, MMMM[achea] Do, YYYY, A h:mm [vazta]',
+ 'llll' => 'ddd, D MMM YYYY, A h:mm [vazta]',
+ ],
+
+ 'calendar' => [
+ 'sameDay' => '[Aiz] LT',
+ 'nextDay' => '[Faleam] LT',
+ 'nextWeek' => '[Ieta to] dddd[,] LT',
+ 'lastDay' => '[Kal] LT',
+ 'lastWeek' => '[Fatlo] dddd[,] LT',
+ 'sameElse' => 'L',
+ ],
+
+ 'months' => ['Janer', 'Febrer', 'Mars', 'Abril', 'Mai', 'Jun', 'Julai', 'Agost', 'Setembr', 'Otubr', 'Novembr', 'Dezembr'],
+ 'months_short' => ['Jan.', 'Feb.', 'Mars', 'Abr.', 'Mai', 'Jun', 'Jul.', 'Ago.', 'Set.', 'Otu.', 'Nov.', 'Dez.'],
+ 'weekdays' => ['Aitar', 'Somar', 'Mongllar', 'Budvar', 'Brestar', 'Sukrar', 'Son\'var'],
+ 'weekdays_short' => ['Ait.', 'Som.', 'Mon.', 'Bud.', 'Bre.', 'Suk.', 'Son.'],
+ 'weekdays_min' => ['Ai', 'Sm', 'Mo', 'Bu', 'Br', 'Su', 'Sn'],
+
+ 'ordinal' => function ($number, $period) {
+ return $number.($period === 'D' ? 'er' : '');
+ },
+
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'rati';
+ }
+ if ($hour < 12) {
+ return 'sokalli';
+ }
+ if ($hour < 16) {
+ return 'donparam';
+ }
+ if ($hour < 20) {
+ return 'sanje';
+ }
+
+ return 'rati';
+ },
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' ani '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw.php
new file mode 100644
index 0000000..c5c850e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Christopher Dell
+ * - Akira Matsuda
+ * - Enrique Vidal
+ * - Simone Carletti
+ * - Henning Kiel
+ * - Aaron Patterson
+ * - Florian Hanke
+ */
+return [
+ 'year' => ':count Johr',
+ 'month' => ':count Monet',
+ 'week' => ':count Woche',
+ 'day' => ':count Tag',
+ 'hour' => ':count Schtund',
+ 'minute' => ':count Minute',
+ 'second' => ':count Sekunde',
+ 'weekdays' => ['Sunntig', 'Mäntig', 'Ziischtig', 'Mittwuch', 'Dunschtig', 'Friitig', 'Samschtig'],
+ 'weekdays_short' => ['Su', 'Mä', 'Zi', 'Mi', 'Du', 'Fr', 'Sa'],
+ 'weekdays_min' => ['Su', 'Mä', 'Zi', 'Mi', 'Du', 'Fr', 'Sa'],
+ 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'September', 'Oktober', 'November', 'Dezember'],
+ 'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
+ 'meridiem' => ['am Vormittag', 'am Namittag'],
+ 'ordinal' => ':number.',
+ 'list' => [', ', ' und '],
+ 'diff_now' => 'now',
+ 'diff_yesterday' => 'geschter',
+ 'diff_tomorrow' => 'moorn',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'Do MMMM YYYY',
+ 'LLL' => 'Do MMMM, HH:mm [Uhr]',
+ 'LLLL' => 'dddd, Do MMMM YYYY, HH:mm [Uhr]',
+ ],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw_CH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw_CH.php
new file mode 100644
index 0000000..0dba9c5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw_CH.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/gsw.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw_FR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw_FR.php
new file mode 100644
index 0000000..e0e7b23
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw_FR.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/gsw.php', [
+ 'meridiem' => ['vorm.', 'nam.'],
+ 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LLL' => 'Do MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, Do MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw_LI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw_LI.php
new file mode 100644
index 0000000..e0e7b23
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gsw_LI.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/gsw.php', [
+ 'meridiem' => ['vorm.', 'nam.'],
+ 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LLL' => 'Do MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, Do MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gu.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gu.php
new file mode 100644
index 0000000..7c7872b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gu.php
@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - Kaushik Thanki
+ * - Josh Soref
+ */
+return [
+ 'year' => 'એક વર્ષ|:count વર્ષ',
+ 'y' => ':countવર્ષ|:countવર્ષો',
+ 'month' => 'એક મહિનો|:count મહિનો',
+ 'm' => ':countમહિનો|:countમહિના',
+ 'week' => ':count અઠવાડિયું|:count અઠવાડિયા',
+ 'w' => ':countઅઠ.|:countઅઠ.',
+ 'day' => 'એક દિવસ|:count દિવસ',
+ 'd' => ':countદિ.|:countદિ.',
+ 'hour' => 'એક કલાક|:count કલાક',
+ 'h' => ':countક.|:countક.',
+ 'minute' => 'એક મિનિટ|:count મિનિટ',
+ 'min' => ':countમિ.|:countમિ.',
+ 'second' => 'અમુક પળો|:count સેકંડ',
+ 's' => ':countસે.|:countસે.',
+ 'ago' => ':time પેહલા',
+ 'from_now' => ':time મા',
+ 'after' => ':time પછી',
+ 'before' => ':time પહેલા',
+ 'diff_now' => 'હમણાં',
+ 'diff_today' => 'આજ',
+ 'diff_yesterday' => 'ગઇકાલે',
+ 'diff_tomorrow' => 'કાલે',
+ 'formats' => [
+ 'LT' => 'A h:mm વાગ્યે',
+ 'LTS' => 'A h:mm:ss વાગ્યે',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, A h:mm વાગ્યે',
+ 'LLLL' => 'dddd, D MMMM YYYY, A h:mm વાગ્યે',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[આજ] LT',
+ 'nextDay' => '[કાલે] LT',
+ 'nextWeek' => 'dddd, LT',
+ 'lastDay' => '[ગઇકાલે] LT',
+ 'lastWeek' => '[પાછલા] dddd, LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'રાત';
+ }
+ if ($hour < 10) {
+ return 'સવાર';
+ }
+ if ($hour < 17) {
+ return 'બપોર';
+ }
+ if ($hour < 20) {
+ return 'સાંજ';
+ }
+
+ return 'રાત';
+ },
+ 'months' => ['જાન્યુઆરી', 'ફેબ્રુઆરી', 'માર્ચ', 'એપ્રિલ', 'મે', 'જૂન', 'જુલાઈ', 'ઑગસ્ટ', 'સપ્ટેમ્બર', 'ઑક્ટ્બર', 'નવેમ્બર', 'ડિસેમ્બર'],
+ 'months_short' => ['જાન્યુ.', 'ફેબ્રુ.', 'માર્ચ', 'એપ્રિ.', 'મે', 'જૂન', 'જુલા.', 'ઑગ.', 'સપ્ટે.', 'ઑક્ટ્.', 'નવે.', 'ડિસે.'],
+ 'weekdays' => ['રવિવાર', 'સોમવાર', 'મંગળવાર', 'બુધ્વાર', 'ગુરુવાર', 'શુક્રવાર', 'શનિવાર'],
+ 'weekdays_short' => ['રવિ', 'સોમ', 'મંગળ', 'બુધ્', 'ગુરુ', 'શુક્ર', 'શનિ'],
+ 'weekdays_min' => ['ર', 'સો', 'મં', 'બુ', 'ગુ', 'શુ', 'શ'],
+ 'list' => [', ', ' અને '],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'weekend' => [0, 0],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gu_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gu_IN.php
new file mode 100644
index 0000000..c578440
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gu_IN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/gu.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/guz.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/guz.php
new file mode 100644
index 0000000..aa9769c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/guz.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Ma', 'Mo'],
+ 'weekdays' => ['Chumapiri', 'Chumatato', 'Chumaine', 'Chumatano', 'Aramisi', 'Ichuma', 'Esabato'],
+ 'weekdays_short' => ['Cpr', 'Ctt', 'Cmn', 'Cmt', 'Ars', 'Icm', 'Est'],
+ 'weekdays_min' => ['Cpr', 'Ctt', 'Cmn', 'Cmt', 'Ars', 'Icm', 'Est'],
+ 'months' => ['Chanuari', 'Feburari', 'Machi', 'Apiriri', 'Mei', 'Juni', 'Chulai', 'Agosti', 'Septemba', 'Okitoba', 'Nobemba', 'Disemba'],
+ 'months_short' => ['Can', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Cul', 'Agt', 'Sep', 'Okt', 'Nob', 'Dis'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+
+ 'month' => ':count omotunyi', // less reliable
+ 'm' => ':count omotunyi', // less reliable
+ 'a_month' => ':count omotunyi', // less reliable
+
+ 'week' => ':count isano naibere', // less reliable
+ 'w' => ':count isano naibere', // less reliable
+ 'a_week' => ':count isano naibere', // less reliable
+
+ 'second' => ':count ibere', // less reliable
+ 's' => ':count ibere', // less reliable
+ 'a_second' => ':count ibere', // less reliable
+
+ 'year' => ':count omwaka',
+ 'y' => ':count omwaka',
+ 'a_year' => ':count omwaka',
+
+ 'day' => ':count rituko',
+ 'd' => ':count rituko',
+ 'a_day' => ':count rituko',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gv.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gv.php
new file mode 100644
index 0000000..7c52b94
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gv.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/gv_GB.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gv_GB.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gv_GB.php
new file mode 100644
index 0000000..6b1168f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gv_GB.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Alastair McKinstry bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['Jerrey-geuree', 'Toshiaght-arree', 'Mayrnt', 'Averil', 'Boaldyn', 'Mean-souree', 'Jerrey-souree', 'Luanistyn', 'Mean-fouyir', 'Jerrey-fouyir', 'Mee Houney', 'Mee ny Nollick'],
+ 'months_short' => ['J-guer', 'T-arree', 'Mayrnt', 'Avrril', 'Boaldyn', 'M-souree', 'J-souree', 'Luanistyn', 'M-fouyir', 'J-fouyir', 'M.Houney', 'M.Nollick'],
+ 'weekdays' => ['Jedoonee', 'Jelhein', 'Jemayrt', 'Jercean', 'Jerdein', 'Jeheiney', 'Jesarn'],
+ 'weekdays_short' => ['Jed', 'Jel', 'Jem', 'Jerc', 'Jerd', 'Jeh', 'Jes'],
+ 'weekdays_min' => ['Jed', 'Jel', 'Jem', 'Jerc', 'Jerd', 'Jeh', 'Jes'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'year' => ':count blein',
+ 'y' => ':count blein',
+ 'a_year' => ':count blein',
+
+ 'month' => ':count mee',
+ 'm' => ':count mee',
+ 'a_month' => ':count mee',
+
+ 'week' => ':count shiaghtin',
+ 'w' => ':count shiaghtin',
+ 'a_week' => ':count shiaghtin',
+
+ 'day' => ':count laa',
+ 'd' => ':count laa',
+ 'a_day' => ':count laa',
+
+ 'hour' => ':count oor',
+ 'h' => ':count oor',
+ 'a_hour' => ':count oor',
+
+ 'minute' => ':count feer veg',
+ 'min' => ':count feer veg',
+ 'a_minute' => ':count feer veg',
+
+ 'second' => ':count derrey',
+ 's' => ':count derrey',
+ 'a_second' => ':count derrey',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha.php
new file mode 100644
index 0000000..cd8e34d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - pablo@mandriva.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM, YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM, YYYY HH:mm',
+ ],
+ 'months' => ['Janairu', 'Faburairu', 'Maris', 'Afirilu', 'Mayu', 'Yuni', 'Yuli', 'Agusta', 'Satumba', 'Oktoba', 'Nuwamba', 'Disamba'],
+ 'months_short' => ['Jan', 'Fab', 'Mar', 'Afi', 'May', 'Yun', 'Yul', 'Agu', 'Sat', 'Okt', 'Nuw', 'Dis'],
+ 'weekdays' => ['Lahadi', 'Litini', 'Talata', 'Laraba', 'Alhamis', 'Jumaʼa', 'Asabar'],
+ 'weekdays_short' => ['Lah', 'Lit', 'Tal', 'Lar', 'Alh', 'Jum', 'Asa'],
+ 'weekdays_min' => ['Lh', 'Li', 'Ta', 'Lr', 'Al', 'Ju', 'As'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => 'shekara :count',
+ 'y' => 'shekara :count',
+ 'a_year' => 'shekara :count',
+
+ 'month' => ':count wátàa',
+ 'm' => ':count wátàa',
+ 'a_month' => ':count wátàa',
+
+ 'week' => ':count mako',
+ 'w' => ':count mako',
+ 'a_week' => ':count mako',
+
+ 'day' => ':count rana',
+ 'd' => ':count rana',
+ 'a_day' => ':count rana',
+
+ 'hour' => ':count áwàa',
+ 'h' => ':count áwàa',
+ 'a_hour' => ':count áwàa',
+
+ 'minute' => 'minti :count',
+ 'min' => 'minti :count',
+ 'a_minute' => 'minti :count',
+
+ 'second' => ':count ná bíyú',
+ 's' => ':count ná bíyú',
+ 'a_second' => ':count ná bíyú',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha_GH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha_GH.php
new file mode 100644
index 0000000..bce5e41
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha_GH.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ha.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha_NE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha_NE.php
new file mode 100644
index 0000000..bce5e41
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha_NE.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ha.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha_NG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha_NG.php
new file mode 100644
index 0000000..bce5e41
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ha_NG.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ha.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hak.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hak.php
new file mode 100644
index 0000000..6c3260e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hak.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/hak_TW.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hak_TW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hak_TW.php
new file mode 100644
index 0000000..fe23986
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hak_TW.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY年MM月DD日',
+ ],
+ 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ 'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'],
+ 'weekdays' => ['禮拜日', '禮拜一', '禮拜二', '禮拜三', '禮拜四', '禮拜五', '禮拜六'],
+ 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['上晝', '下晝'],
+
+ 'year' => ':count ngien11',
+ 'y' => ':count ngien11',
+ 'a_year' => ':count ngien11',
+
+ 'month' => ':count ngie̍t',
+ 'm' => ':count ngie̍t',
+ 'a_month' => ':count ngie̍t',
+
+ 'week' => ':count lî-pai',
+ 'w' => ':count lî-pai',
+ 'a_week' => ':count lî-pai',
+
+ 'day' => ':count ngit',
+ 'd' => ':count ngit',
+ 'a_day' => ':count ngit',
+
+ 'hour' => ':count sṳ̀',
+ 'h' => ':count sṳ̀',
+ 'a_hour' => ':count sṳ̀',
+
+ 'minute' => ':count fûn',
+ 'min' => ':count fûn',
+ 'a_minute' => ':count fûn',
+
+ 'second' => ':count miéu',
+ 's' => ':count miéu',
+ 'a_second' => ':count miéu',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/haw.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/haw.php
new file mode 100644
index 0000000..51715d8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/haw.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'months' => ['Ianuali', 'Pepeluali', 'Malaki', 'ʻApelila', 'Mei', 'Iune', 'Iulai', 'ʻAukake', 'Kepakemapa', 'ʻOkakopa', 'Nowemapa', 'Kekemapa'],
+ 'months_short' => ['Ian.', 'Pep.', 'Mal.', 'ʻAp.', 'Mei', 'Iun.', 'Iul.', 'ʻAu.', 'Kep.', 'ʻOk.', 'Now.', 'Kek.'],
+ 'weekdays' => ['Lāpule', 'Poʻakahi', 'Poʻalua', 'Poʻakolu', 'Poʻahā', 'Poʻalima', 'Poʻaono'],
+ 'weekdays_short' => ['LP', 'P1', 'P2', 'P3', 'P4', 'P5', 'P6'],
+ 'weekdays_min' => ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd, D MMMM YYYY h:mm a',
+ ],
+
+ 'year' => ':count makahiki',
+ 'y' => ':count makahiki',
+ 'a_year' => ':count makahiki',
+
+ 'month' => ':count mahina',
+ 'm' => ':count mahina',
+ 'a_month' => ':count mahina',
+
+ 'week' => ':count pule',
+ 'w' => ':count pule',
+ 'a_week' => ':count pule',
+
+ 'day' => ':count lā',
+ 'd' => ':count lā',
+ 'a_day' => ':count lā',
+
+ 'hour' => ':count hola',
+ 'h' => ':count hola',
+ 'a_hour' => ':count hola',
+
+ 'minute' => ':count minuke',
+ 'min' => ':count minuke',
+ 'a_minute' => ':count minuke',
+
+ 'second' => ':count lua',
+ 's' => ':count lua',
+ 'a_second' => ':count lua',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/he.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/he.php
new file mode 100644
index 0000000..c3fb3e9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/he.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Daniel Cohen Gindi
+ * - JD Isaacks
+ * - Itai Nathaniel
+ * - GabMic
+ * - Yaakov Dahan (yakidahan)
+ */
+return [
+ 'year' => 'שנה|{2}שנתיים|:count שנים',
+ 'y' => 'שנה|:count שנ׳',
+ 'month' => 'חודש|{2}חודשיים|:count חודשים',
+ 'm' => 'חודש|:count חו׳',
+ 'week' => 'שבוע|{2}שבועיים|:count שבועות',
+ 'w' => 'שבוע|:count שב׳',
+ 'day' => 'יום|{2}יומיים|:count ימים',
+ 'd' => 'יום|:count ימ׳',
+ 'hour' => 'שעה|{2}שעתיים|:count שעות',
+ 'h' => 'שעה|:count שע׳',
+ 'minute' => 'דקה|{2}שתי דקות|:count דקות',
+ 'min' => 'דקה|:count דק׳',
+ 'second' => 'שנייה|:count שניות',
+ 'a_second' => 'כמה שניות|:count שניות',
+ 's' => 'שניה|:count שנ׳',
+ 'ago' => 'לפני :time',
+ 'from_now' => 'בעוד :time מעכשיו',
+ 'after' => 'אחרי :time',
+ 'before' => 'לפני :time',
+ 'diff_now' => 'עכשיו',
+ 'diff_today' => 'היום',
+ 'diff_today_regexp' => 'היום(?:\\s+ב־)?',
+ 'diff_yesterday' => 'אתמול',
+ 'diff_yesterday_regexp' => 'אתמול(?:\\s+ב־)?',
+ 'diff_tomorrow' => 'מחר',
+ 'diff_tomorrow_regexp' => 'מחר(?:\\s+ב־)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D [ב]MMMM YYYY',
+ 'LLL' => 'D [ב]MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D [ב]MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[היום ב־]LT',
+ 'nextDay' => '[מחר ב־]LT',
+ 'nextWeek' => 'dddd [בשעה] LT',
+ 'lastDay' => '[אתמול ב־]LT',
+ 'lastWeek' => '[ביום] dddd [האחרון בשעה] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour, $minute, $isLower) {
+ if ($hour < 5) {
+ return 'לפנות בוקר';
+ }
+ if ($hour < 10) {
+ return 'בבוקר';
+ }
+ if ($hour < 12) {
+ return $isLower ? 'לפנה"צ' : 'לפני הצהריים';
+ }
+ if ($hour < 18) {
+ return $isLower ? 'אחה"צ' : 'אחרי הצהריים';
+ }
+
+ return 'בערב';
+ },
+ 'months' => ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'],
+ 'months_short' => ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳', 'דצמ׳'],
+ 'weekdays' => ['ראשון', 'שני', 'שלישי', 'רביעי', 'חמישי', 'שישי', 'שבת'],
+ 'weekdays_short' => ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'],
+ 'weekdays_min' => ['א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ש'],
+ 'list' => [', ', ' ו -'],
+ 'weekend' => [5, 6],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/he_IL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/he_IL.php
new file mode 100644
index 0000000..57c4fec
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/he_IL.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/he.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hi.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hi.php
new file mode 100644
index 0000000..70c57a2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hi.php
@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - abhimanyu003
+ * - Josh Soref
+ * - JD Isaacks
+ */
+return [
+ 'year' => 'एक वर्ष|:count वर्ष',
+ 'y' => '1 वर्ष|:count वर्षों',
+ 'month' => 'एक महीने|:count महीने',
+ 'm' => '1 माह|:count महीने',
+ 'week' => '1 सप्ताह|:count सप्ताह',
+ 'w' => '1 सप्ताह|:count सप्ताह',
+ 'day' => 'एक दिन|:count दिन',
+ 'd' => '1 दिन|:count दिनों',
+ 'hour' => 'एक घंटा|:count घंटे',
+ 'h' => '1 घंटा|:count घंटे',
+ 'minute' => 'एक मिनट|:count मिनट',
+ 'min' => '1 मिनट|:count मिनटों',
+ 'second' => 'कुछ ही क्षण|:count सेकंड',
+ 's' => '1 सेकंड|:count सेकंड',
+ 'ago' => ':time पहले',
+ 'from_now' => ':time में',
+ 'after' => ':time के बाद',
+ 'before' => ':time के पहले',
+ 'diff_now' => 'अब',
+ 'diff_today' => 'आज',
+ 'diff_yesterday' => 'कल',
+ 'diff_tomorrow' => 'कल',
+ 'formats' => [
+ 'LT' => 'A h:mm बजे',
+ 'LTS' => 'A h:mm:ss बजे',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, A h:mm बजे',
+ 'LLLL' => 'dddd, D MMMM YYYY, A h:mm बजे',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[आज] LT',
+ 'nextDay' => '[कल] LT',
+ 'nextWeek' => 'dddd, LT',
+ 'lastDay' => '[कल] LT',
+ 'lastWeek' => '[पिछले] dddd, LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'रात';
+ }
+ if ($hour < 10) {
+ return 'सुबह';
+ }
+ if ($hour < 17) {
+ return 'दोपहर';
+ }
+ if ($hour < 20) {
+ return 'शाम';
+ }
+
+ return 'रात';
+ },
+ 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
+ 'months_short' => ['जन.', 'फ़र.', 'मार्च', 'अप्रै.', 'मई', 'जून', 'जुल.', 'अग.', 'सित.', 'अक्टू.', 'नव.', 'दिस.'],
+ 'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरूवार', 'शुक्रवार', 'शनिवार'],
+ 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरू', 'शुक्र', 'शनि'],
+ 'weekdays_min' => ['र', 'सो', 'मं', 'बु', 'गु', 'शु', 'श'],
+ 'list' => [', ', ' और '],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'weekend' => [0, 0],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hi_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hi_IN.php
new file mode 100644
index 0000000..ac30299
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hi_IN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/hi.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hif.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hif.php
new file mode 100644
index 0000000..65791dd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hif.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/hif_FJ.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hif_FJ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hif_FJ.php
new file mode 100644
index 0000000..30ad5e7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hif_FJ.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'dddd DD MMM YYYY',
+ ],
+ 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ 'weekdays' => ['Ravivar', 'Somvar', 'Mangalvar', 'Budhvar', 'Guruvar', 'Shukravar', 'Shanivar'],
+ 'weekdays_short' => ['Ravi', 'Som', 'Mangal', 'Budh', 'Guru', 'Shukra', 'Shani'],
+ 'weekdays_min' => ['Ravi', 'Som', 'Mangal', 'Budh', 'Guru', 'Shukra', 'Shani'],
+ 'meridiem' => ['Purvahan', 'Aparaahna'],
+
+ 'hour' => ':count minit', // less reliable
+ 'h' => ':count minit', // less reliable
+ 'a_hour' => ':count minit', // less reliable
+
+ 'year' => ':count saal',
+ 'y' => ':count saal',
+ 'a_year' => ':count saal',
+
+ 'month' => ':count Mahina',
+ 'm' => ':count Mahina',
+ 'a_month' => ':count Mahina',
+
+ 'week' => ':count Hafta',
+ 'w' => ':count Hafta',
+ 'a_week' => ':count Hafta',
+
+ 'day' => ':count Din',
+ 'd' => ':count Din',
+ 'a_day' => ':count Din',
+
+ 'minute' => ':count Minit',
+ 'min' => ':count Minit',
+ 'a_minute' => ':count Minit',
+
+ 'second' => ':count Second',
+ 's' => ':count Second',
+ 'a_second' => ':count Second',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hne.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hne.php
new file mode 100644
index 0000000..4bcb05c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hne.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/hne_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hne_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hne_IN.php
new file mode 100644
index 0000000..a5ca758
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hne_IN.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Red Hat, Pune bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अपरेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितमबर', 'अकटूबर', 'नवमबर', 'दिसमबर'],
+ 'months_short' => ['जन', 'फर', 'मार्च', 'अप', 'मई', 'जून', 'जुला', 'अग', 'सित', 'अकटू', 'नव', 'दिस'],
+ 'weekdays' => ['इतवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'बिरसपत', 'सुकरवार', 'सनिवार'],
+ 'weekdays_short' => ['इत', 'सोम', 'मंग', 'बुध', 'बिर', 'सुक', 'सनि'],
+ 'weekdays_min' => ['इत', 'सोम', 'मंग', 'बुध', 'बिर', 'सुक', 'सनि'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['बिहिनियाँ', 'मंझनियाँ'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hr.php
new file mode 100644
index 0000000..acb7e92
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hr.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - Tim Fish
+ * - shaishavgandhi05
+ * - Serhan Apaydın
+ * - JD Isaacks
+ * - tomhorvat
+ * - Josh Soref
+ * - François B
+ * - shaishavgandhi05
+ * - Serhan Apaydın
+ * - JD Isaacks
+ * - tomhorvat
+ * - Stjepan Majdak
+ * - Vanja Retkovac (vr00)
+ */
+return [
+ 'year' => ':count godinu|:count godine|:count godina',
+ 'y' => ':count god.|:count god.|:count god.',
+ 'month' => ':count mjesec|:count mjeseca|:count mjeseci',
+ 'm' => ':count mj.|:count mj.|:count mj.',
+ 'week' => ':count tjedan|:count tjedna|:count tjedana',
+ 'w' => ':count tj.|:count tj.|:count tj.',
+ 'day' => ':count dan|:count dana|:count dana',
+ 'd' => ':count d.|:count d.|:count d.',
+ 'hour' => ':count sat|:count sata|:count sati',
+ 'h' => ':count sat|:count sata|:count sati',
+ 'minute' => ':count minutu|:count minute|:count minuta',
+ 'min' => ':count min.|:count min.|:count min.',
+ 'second' => ':count sekundu|:count sekunde|:count sekundi',
+ 'a_second' => 'nekoliko sekundi|:count sekunde|:count sekundi',
+ 's' => ':count sek.|:count sek.|:count sek.',
+ 'ago' => 'prije :time',
+ 'from_now' => 'za :time',
+ 'after' => ':time poslije',
+ 'before' => ':time prije',
+ 'diff_now' => 'sad',
+ 'diff_today' => 'danas',
+ 'diff_today_regexp' => 'danas(?:\\s+u)?',
+ 'diff_yesterday' => 'jučer',
+ 'diff_yesterday_regexp' => 'jučer(?:\\s+u)?',
+ 'diff_tomorrow' => 'sutra',
+ 'diff_tomorrow_regexp' => 'sutra(?:\\s+u)?',
+ 'diff_before_yesterday' => 'prekjučer',
+ 'diff_after_tomorrow' => 'prekosutra',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'D. M. YYYY.',
+ 'LL' => 'D. MMMM YYYY.',
+ 'LLL' => 'D. MMMM YYYY. H:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY. H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[danas u] LT',
+ 'nextDay' => '[sutra u] LT',
+ 'nextWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[u] [nedjelju] [u] LT';
+ case 3:
+ return '[u] [srijedu] [u] LT';
+ case 6:
+ return '[u] [subotu] [u] LT';
+ default:
+ return '[u] dddd [u] LT';
+ }
+ },
+ 'lastDay' => '[jučer u] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ case 3:
+ return '[prošlu] dddd [u] LT';
+ case 6:
+ return '[prošle] [subote] [u] LT';
+ default:
+ return '[prošli] dddd [u] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja', 'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'],
+ 'months_standalone' => ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj', 'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'],
+ 'months_short' => ['sij.', 'velj.', 'ožu.', 'tra.', 'svi.', 'lip.', 'srp.', 'kol.', 'ruj.', 'lis.', 'stu.', 'pro.'],
+ 'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
+ 'weekdays' => ['nedjelju', 'ponedjeljak', 'utorak', 'srijedu', 'četvrtak', 'petak', 'subotu'],
+ 'weekdays_standalone' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
+ 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'],
+ 'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' i '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hr_BA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hr_BA.php
new file mode 100644
index 0000000..7763a45
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hr_BA.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - DarkoDevelop
+ */
+return array_replace_recursive(require __DIR__.'/hr.php', [
+ 'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
+ 'weekdays_short' => ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
+ 'weekdays_min' => ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
+ 'months' => ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja', 'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'],
+ 'months_short' => ['sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp', 'kol', 'ruj', 'lis', 'stu', 'pro'],
+ 'months_standalone' => ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj', 'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D. M. yy.',
+ 'LL' => 'D. MMM YYYY.',
+ 'LLL' => 'D. MMMM YYYY. HH:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY. HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hr_HR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hr_HR.php
new file mode 100644
index 0000000..2ae141d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hr_HR.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/hr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hsb.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hsb.php
new file mode 100644
index 0000000..3537b8b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hsb.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/hsb_DE.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hsb_DE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hsb_DE.php
new file mode 100644
index 0000000..6ba2271
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hsb_DE.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Information from Michael Wolf Andrzej Krzysztofowicz ankry@mif.pg.gda.pl
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'DD. MMMM YYYY',
+ 'LLL' => 'DD. MMMM, HH:mm [hodź.]',
+ 'LLLL' => 'dddd, DD. MMMM YYYY, HH:mm [hodź.]',
+ ],
+ 'months' => ['januara', 'februara', 'měrca', 'apryla', 'meje', 'junija', 'julija', 'awgusta', 'septembra', 'oktobra', 'nowembra', 'decembra'],
+ 'months_short' => ['Jan', 'Feb', 'Měr', 'Apr', 'Mej', 'Jun', 'Jul', 'Awg', 'Sep', 'Okt', 'Now', 'Dec'],
+ 'weekdays' => ['Njedźela', 'Póndźela', 'Wutora', 'Srjeda', 'Štvórtk', 'Pjatk', 'Sobota'],
+ 'weekdays_short' => ['Nj', 'Pó', 'Wu', 'Sr', 'Št', 'Pj', 'So'],
+ 'weekdays_min' => ['Nj', 'Pó', 'Wu', 'Sr', 'Št', 'Pj', 'So'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'year' => ':count lěto',
+ 'y' => ':count lěto',
+ 'a_year' => ':count lěto',
+
+ 'month' => ':count měsac',
+ 'm' => ':count měsac',
+ 'a_month' => ':count měsac',
+
+ 'week' => ':count tydźeń',
+ 'w' => ':count tydźeń',
+ 'a_week' => ':count tydźeń',
+
+ 'day' => ':count dźeń',
+ 'd' => ':count dźeń',
+ 'a_day' => ':count dźeń',
+
+ 'hour' => ':count hodźina',
+ 'h' => ':count hodźina',
+ 'a_hour' => ':count hodźina',
+
+ 'minute' => ':count chwila',
+ 'min' => ':count chwila',
+ 'a_minute' => ':count chwila',
+
+ 'second' => ':count druhi',
+ 's' => ':count druhi',
+ 'a_second' => ':count druhi',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ht.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ht.php
new file mode 100644
index 0000000..ebd12ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ht.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ht_HT.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ht_HT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ht_HT.php
new file mode 100644
index 0000000..139b813
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ht_HT.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['janvye', 'fevriye', 'mas', 'avril', 'me', 'jen', 'jiyè', 'out', 'septanm', 'oktòb', 'novanm', 'desanm'],
+ 'months_short' => ['jan', 'fev', 'mas', 'avr', 'me', 'jen', 'jiy', 'out', 'sep', 'okt', 'nov', 'des'],
+ 'weekdays' => ['dimanch', 'lendi', 'madi', 'mèkredi', 'jedi', 'vandredi', 'samdi'],
+ 'weekdays_short' => ['dim', 'len', 'mad', 'mèk', 'jed', 'van', 'sam'],
+ 'weekdays_min' => ['dim', 'len', 'mad', 'mèk', 'jed', 'van', 'sam'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count lane',
+ 'y' => ':count lane',
+ 'a_year' => ':count lane',
+
+ 'month' => 'mwa :count',
+ 'm' => 'mwa :count',
+ 'a_month' => 'mwa :count',
+
+ 'week' => 'semèn :count',
+ 'w' => 'semèn :count',
+ 'a_week' => 'semèn :count',
+
+ 'day' => ':count jou',
+ 'd' => ':count jou',
+ 'a_day' => ':count jou',
+
+ 'hour' => ':count lè',
+ 'h' => ':count lè',
+ 'a_hour' => ':count lè',
+
+ 'minute' => ':count minit',
+ 'min' => ':count minit',
+ 'a_minute' => ':count minit',
+
+ 'second' => ':count segonn',
+ 's' => ':count segonn',
+ 'a_second' => ':count segonn',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hu.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hu.php
new file mode 100644
index 0000000..673f9dc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hu.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Adam Brunner
+ * - Brett Johnson
+ * - balping
+ */
+$huWeekEndings = ['vasárnap', 'hétfőn', 'kedden', 'szerdán', 'csütörtökön', 'pénteken', 'szombaton'];
+
+return [
+ 'year' => ':count év',
+ 'y' => ':count év',
+ 'month' => ':count hónap',
+ 'm' => ':count hónap',
+ 'week' => ':count hét',
+ 'w' => ':count hét',
+ 'day' => ':count nap',
+ 'd' => ':count nap',
+ 'hour' => ':count óra',
+ 'h' => ':count óra',
+ 'minute' => ':count perc',
+ 'min' => ':count perc',
+ 'second' => ':count másodperc',
+ 's' => ':count másodperc',
+ 'ago' => ':time',
+ 'from_now' => ':time múlva',
+ 'after' => ':time később',
+ 'before' => ':time korábban',
+ 'year_ago' => ':count éve',
+ 'y_ago' => ':count éve',
+ 'month_ago' => ':count hónapja',
+ 'm_ago' => ':count hónapja',
+ 'week_ago' => ':count hete',
+ 'w_ago' => ':count hete',
+ 'day_ago' => ':count napja',
+ 'd_ago' => ':count napja',
+ 'hour_ago' => ':count órája',
+ 'h_ago' => ':count órája',
+ 'minute_ago' => ':count perce',
+ 'min_ago' => ':count perce',
+ 'second_ago' => ':count másodperce',
+ 's_ago' => ':count másodperce',
+ 'year_after' => ':count évvel',
+ 'y_after' => ':count évvel',
+ 'month_after' => ':count hónappal',
+ 'm_after' => ':count hónappal',
+ 'week_after' => ':count héttel',
+ 'w_after' => ':count héttel',
+ 'day_after' => ':count nappal',
+ 'd_after' => ':count nappal',
+ 'hour_after' => ':count órával',
+ 'h_after' => ':count órával',
+ 'minute_after' => ':count perccel',
+ 'min_after' => ':count perccel',
+ 'second_after' => ':count másodperccel',
+ 's_after' => ':count másodperccel',
+ 'year_before' => ':count évvel',
+ 'y_before' => ':count évvel',
+ 'month_before' => ':count hónappal',
+ 'm_before' => ':count hónappal',
+ 'week_before' => ':count héttel',
+ 'w_before' => ':count héttel',
+ 'day_before' => ':count nappal',
+ 'd_before' => ':count nappal',
+ 'hour_before' => ':count órával',
+ 'h_before' => ':count órával',
+ 'minute_before' => ':count perccel',
+ 'min_before' => ':count perccel',
+ 'second_before' => ':count másodperccel',
+ 's_before' => ':count másodperccel',
+ 'months' => ['január', 'február', 'március', 'április', 'május', 'június', 'július', 'augusztus', 'szeptember', 'október', 'november', 'december'],
+ 'months_short' => ['jan.', 'feb.', 'márc.', 'ápr.', 'máj.', 'jún.', 'júl.', 'aug.', 'szept.', 'okt.', 'nov.', 'dec.'],
+ 'weekdays' => ['vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök', 'péntek', 'szombat'],
+ 'weekdays_short' => ['vas', 'hét', 'kedd', 'sze', 'csüt', 'pén', 'szo'],
+ 'weekdays_min' => ['v', 'h', 'k', 'sze', 'cs', 'p', 'sz'],
+ 'ordinal' => ':number.',
+ 'diff_now' => 'most',
+ 'diff_today' => 'ma',
+ 'diff_yesterday' => 'tegnap',
+ 'diff_tomorrow' => 'holnap',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'YYYY.MM.DD.',
+ 'LL' => 'YYYY. MMMM D.',
+ 'LLL' => 'YYYY. MMMM D. H:mm',
+ 'LLLL' => 'YYYY. MMMM D., dddd H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[ma] LT[-kor]',
+ 'nextDay' => '[holnap] LT[-kor]',
+ 'nextWeek' => function (\Carbon\CarbonInterface $date) use ($huWeekEndings) {
+ return '['.$huWeekEndings[$date->dayOfWeek].'] LT[-kor]';
+ },
+ 'lastDay' => '[tegnap] LT[-kor]',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) use ($huWeekEndings) {
+ return '[múlt '.$huWeekEndings[$date->dayOfWeek].'] LT[-kor]';
+ },
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['DE', 'DU'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' és '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hu_HU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hu_HU.php
new file mode 100644
index 0000000..b33a631
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hu_HU.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/hu.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hy.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hy.php
new file mode 100644
index 0000000..8b12994
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hy.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - mhamlet
+ */
+return [
+ 'year' => ':count տարի',
+ 'a_year' => 'տարի|:count տարի',
+ 'y' => ':countտ',
+ 'month' => ':count ամիս',
+ 'a_month' => 'ամիս|:count ամիս',
+ 'm' => ':countամ',
+ 'week' => ':count շաբաթ',
+ 'a_week' => 'շաբաթ|:count շաբաթ',
+ 'w' => ':countշ',
+ 'day' => ':count օր',
+ 'a_day' => 'օր|:count օր',
+ 'd' => ':countօր',
+ 'hour' => ':count ժամ',
+ 'a_hour' => 'ժամ|:count ժամ',
+ 'h' => ':countժ',
+ 'minute' => ':count րոպե',
+ 'a_minute' => 'րոպե|:count րոպե',
+ 'min' => ':countր',
+ 'second' => ':count վայրկյան',
+ 'a_second' => 'մի քանի վայրկյան|:count վայրկյան',
+ 's' => ':countվրկ',
+ 'ago' => ':time առաջ',
+ 'from_now' => ':timeից',
+ 'after' => ':time հետո',
+ 'before' => ':time առաջ',
+ 'diff_now' => 'հիմա',
+ 'diff_today' => 'այսօր',
+ 'diff_yesterday' => 'երեկ',
+ 'diff_tomorrow' => 'վաղը',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY թ.',
+ 'LLL' => 'D MMMM YYYY թ., HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY թ., HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[այսօր] LT',
+ 'nextDay' => '[վաղը] LT',
+ 'nextWeek' => 'dddd [օրը ժամը] LT',
+ 'lastDay' => '[երեկ] LT',
+ 'lastWeek' => '[անցած] dddd [օրը ժամը] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ case 'DDD':
+ case 'w':
+ case 'W':
+ case 'DDDo':
+ return $number.($number === 1 ? '-ին' : '-րդ');
+ default:
+ return $number;
+ }
+ },
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'գիշերվա';
+ }
+ if ($hour < 12) {
+ return 'առավոտվա';
+ }
+ if ($hour < 17) {
+ return 'ցերեկվա';
+ }
+
+ return 'երեկոյան';
+ },
+ 'months' => ['հունվարի', 'փետրվարի', 'մարտի', 'ապրիլի', 'մայիսի', 'հունիսի', 'հուլիսի', 'օգոստոսի', 'սեպտեմբերի', 'հոկտեմբերի', 'նոյեմբերի', 'դեկտեմբերի'],
+ 'months_standalone' => ['հունվար', 'փետրվար', 'մարտ', 'ապրիլ', 'մայիս', 'հունիս', 'հուլիս', 'օգոստոս', 'սեպտեմբեր', 'հոկտեմբեր', 'նոյեմբեր', 'դեկտեմբեր'],
+ 'months_short' => ['հնվ', 'փտր', 'մրտ', 'ապր', 'մյս', 'հնս', 'հլս', 'օգս', 'սպտ', 'հկտ', 'նմբ', 'դկտ'],
+ 'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
+ 'weekdays' => ['կիրակի', 'երկուշաբթի', 'երեքշաբթի', 'չորեքշաբթի', 'հինգշաբթի', 'ուրբաթ', 'շաբաթ'],
+ 'weekdays_short' => ['կրկ', 'երկ', 'երք', 'չրք', 'հնգ', 'ուրբ', 'շբթ'],
+ 'weekdays_min' => ['կրկ', 'երկ', 'երք', 'չրք', 'հնգ', 'ուրբ', 'շբթ'],
+ 'list' => [', ', ' եւ '],
+ 'first_day_of_week' => 1,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hy_AM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hy_AM.php
new file mode 100644
index 0000000..4587df5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/hy_AM.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - Tim Fish
+ * - Serhan Apaydın
+ * - JD Isaacks
+ */
+return array_replace_recursive(require __DIR__.'/hy.php', [
+ 'from_now' => ':time հետո',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/i18n.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/i18n.php
new file mode 100644
index 0000000..d19e4f4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/i18n.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY-MM-DD',
+ ],
+ 'months' => ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
+ 'months_short' => ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
+ 'weekdays' => ['1', '2', '3', '4', '5', '6', '7'],
+ 'weekdays_short' => ['1', '2', '3', '4', '5', '6', '7'],
+ 'weekdays_min' => ['1', '2', '3', '4', '5', '6', '7'],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ia.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ia.php
new file mode 100644
index 0000000..0a0d5e6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ia.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ia_FR.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ia_FR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ia_FR.php
new file mode 100644
index 0000000..de4b2fa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ia_FR.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Fedora Project Nik Kalach nikka@fedoraproject.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['januario', 'februario', 'martio', 'april', 'maio', 'junio', 'julio', 'augusto', 'septembre', 'octobre', 'novembre', 'decembre'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'],
+ 'weekdays' => ['dominica', 'lunedi', 'martedi', 'mercuridi', 'jovedi', 'venerdi', 'sabbato'],
+ 'weekdays_short' => ['dom', 'lun', 'mar', 'mer', 'jov', 'ven', 'sab'],
+ 'weekdays_min' => ['dom', 'lun', 'mar', 'mer', 'jov', 'ven', 'sab'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'year' => 'anno :count',
+ 'y' => 'anno :count',
+ 'a_year' => 'anno :count',
+
+ 'month' => ':count mense',
+ 'm' => ':count mense',
+ 'a_month' => ':count mense',
+
+ 'week' => ':count septimana',
+ 'w' => ':count septimana',
+ 'a_week' => ':count septimana',
+
+ 'day' => ':count die',
+ 'd' => ':count die',
+ 'a_day' => ':count die',
+
+ 'hour' => ':count hora',
+ 'h' => ':count hora',
+ 'a_hour' => ':count hora',
+
+ 'minute' => ':count minuscule',
+ 'min' => ':count minuscule',
+ 'a_minute' => ':count minuscule',
+
+ 'second' => ':count secunda',
+ 's' => ':count secunda',
+ 'a_second' => ':count secunda',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/id.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/id.php
new file mode 100644
index 0000000..afaf78f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/id.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - du
+ * - JD Isaacks
+ * - Nafies Luthfi
+ * - Raymundus Jati Primanda (mundusjp)
+ * - diankur313
+ * - a-wip0
+ */
+return [
+ 'year' => ':count tahun',
+ 'a_year' => '{1}setahun|]1,Inf[:count tahun',
+ 'y' => ':countthn',
+ 'month' => ':count bulan',
+ 'a_month' => '{1}sebulan|]1,Inf[:count bulan',
+ 'm' => ':countbln',
+ 'week' => ':count minggu',
+ 'a_week' => '{1}seminggu|]1,Inf[:count minggu',
+ 'w' => ':countmgg',
+ 'day' => ':count hari',
+ 'a_day' => '{1}sehari|]1,Inf[:count hari',
+ 'd' => ':counthr',
+ 'hour' => ':count jam',
+ 'a_hour' => '{1}sejam|]1,Inf[:count jam',
+ 'h' => ':countj',
+ 'minute' => ':count menit',
+ 'a_minute' => '{1}semenit|]1,Inf[:count menit',
+ 'min' => ':countmnt',
+ 'second' => ':count detik',
+ 'a_second' => '{1}beberapa detik|]1,Inf[:count detik',
+ 's' => ':countdt',
+ 'ago' => ':time yang lalu',
+ 'from_now' => ':time dari sekarang',
+ 'after' => ':time setelahnya',
+ 'before' => ':time sebelumnya',
+ 'diff_now' => 'sekarang',
+ 'diff_today' => 'Hari',
+ 'diff_today_regexp' => 'Hari(?:\\s+ini)?(?:\\s+pukul)?',
+ 'diff_yesterday' => 'kemarin',
+ 'diff_yesterday_regexp' => 'Kemarin(?:\\s+pukul)?',
+ 'diff_tomorrow' => 'besok',
+ 'diff_tomorrow_regexp' => 'Besok(?:\\s+pukul)?',
+ 'formats' => [
+ 'LT' => 'HH.mm',
+ 'LTS' => 'HH.mm.ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY [pukul] HH.mm',
+ 'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Hari ini pukul] LT',
+ 'nextDay' => '[Besok pukul] LT',
+ 'nextWeek' => 'dddd [pukul] LT',
+ 'lastDay' => '[Kemarin pukul] LT',
+ 'lastWeek' => 'dddd [lalu pukul] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour) {
+ if ($hour < 11) {
+ return 'pagi';
+ }
+ if ($hour < 15) {
+ return 'siang';
+ }
+ if ($hour < 19) {
+ return 'sore';
+ }
+
+ return 'malam';
+ },
+ 'months' => ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agt', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'weekdays' => ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'],
+ 'weekdays_short' => ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
+ 'weekdays_min' => ['Mg', 'Sn', 'Sl', 'Rb', 'Km', 'Jm', 'Sb'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' dan '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/id_ID.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/id_ID.php
new file mode 100644
index 0000000..406112a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/id_ID.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/id.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ig.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ig.php
new file mode 100644
index 0000000..de51e9c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ig.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ig_NG.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ig_NG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ig_NG.php
new file mode 100644
index 0000000..0034e35
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ig_NG.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - pablo@mandriva.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['Jenụwarị', 'Febrụwarị', 'Maachị', 'Eprel', 'Mee', 'Juun', 'Julaị', 'Ọgọọst', 'Septemba', 'Ọktoba', 'Novemba', 'Disemba'],
+ 'months_short' => ['Jen', 'Feb', 'Maa', 'Epr', 'Mee', 'Juu', 'Jul', 'Ọgọ', 'Sep', 'Ọkt', 'Nov', 'Dis'],
+ 'weekdays' => ['sọnde', 'mọnde', 'tuzde', 'wenzde', 'tọsde', 'fraịde', 'satọde'],
+ 'weekdays_short' => ['sọn', 'mọn', 'tuz', 'wen', 'tọs', 'fra', 'sat'],
+ 'weekdays_min' => ['sọn', 'mọn', 'tuz', 'wen', 'tọs', 'fra', 'sat'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => 'afo :count',
+ 'y' => 'afo :count',
+ 'a_year' => 'afo :count',
+
+ 'month' => 'önwa :count',
+ 'm' => 'önwa :count',
+ 'a_month' => 'önwa :count',
+
+ 'week' => 'izu :count',
+ 'w' => 'izu :count',
+ 'a_week' => 'izu :count',
+
+ 'day' => 'ụbọchị :count',
+ 'd' => 'ụbọchị :count',
+ 'a_day' => 'ụbọchị :count',
+
+ 'hour' => 'awa :count',
+ 'h' => 'awa :count',
+ 'a_hour' => 'awa :count',
+
+ 'minute' => 'minit :count',
+ 'min' => 'minit :count',
+ 'a_minute' => 'minit :count',
+
+ 'second' => 'sekọnd :count',
+ 's' => 'sekọnd :count',
+ 'a_second' => 'sekọnd :count',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ii.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ii.php
new file mode 100644
index 0000000..30f8374
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ii.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['ꎸꄑ', 'ꁯꋒ'],
+ 'weekdays' => ['ꑭꆏꑍ', 'ꆏꊂꋍ', 'ꆏꊂꑍ', 'ꆏꊂꌕ', 'ꆏꊂꇖ', 'ꆏꊂꉬ', 'ꆏꊂꃘ'],
+ 'weekdays_short' => ['ꑭꆏ', 'ꆏꋍ', 'ꆏꑍ', 'ꆏꌕ', 'ꆏꇖ', 'ꆏꉬ', 'ꆏꃘ'],
+ 'weekdays_min' => ['ꑭꆏ', 'ꆏꋍ', 'ꆏꑍ', 'ꆏꌕ', 'ꆏꇖ', 'ꆏꉬ', 'ꆏꃘ'],
+ 'months' => null,
+ 'months_short' => ['ꋍꆪ', 'ꑍꆪ', 'ꌕꆪ', 'ꇖꆪ', 'ꉬꆪ', 'ꃘꆪ', 'ꏃꆪ', 'ꉆꆪ', 'ꈬꆪ', 'ꊰꆪ', 'ꊰꊪꆪ', 'ꊰꑋꆪ'],
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'YYYY-MM-dd',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'YYYY MMMM D h:mm a',
+ 'LLLL' => 'YYYY MMMM D, dddd h:mm a',
+ ],
+
+ 'year' => ':count ꒉ', // less reliable
+ 'y' => ':count ꒉ', // less reliable
+ 'a_year' => ':count ꒉ', // less reliable
+
+ 'month' => ':count ꆪ',
+ 'm' => ':count ꆪ',
+ 'a_month' => ':count ꆪ',
+
+ 'week' => ':count ꏃ', // less reliable
+ 'w' => ':count ꏃ', // less reliable
+ 'a_week' => ':count ꏃ', // less reliable
+
+ 'day' => ':count ꏜ', // less reliable
+ 'd' => ':count ꏜ', // less reliable
+ 'a_day' => ':count ꏜ', // less reliable
+
+ 'hour' => ':count ꄮꈉ',
+ 'h' => ':count ꄮꈉ',
+ 'a_hour' => ':count ꄮꈉ',
+
+ 'minute' => ':count ꀄꊭ', // less reliable
+ 'min' => ':count ꀄꊭ', // less reliable
+ 'a_minute' => ':count ꀄꊭ', // less reliable
+
+ 'second' => ':count ꇅ', // less reliable
+ 's' => ':count ꇅ', // less reliable
+ 'a_second' => ':count ꇅ', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ik.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ik.php
new file mode 100644
index 0000000..7a13aa2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ik.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ik_CA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ik_CA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ik_CA.php
new file mode 100644
index 0000000..bb2a109
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ik_CA.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - pablo@mandriva.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['Siqiññaatchiaq', 'Siqiññaasrugruk', 'Paniqsiqsiivik', 'Qilġich Tatqiat', 'Suppivik', 'Iġñivik', 'Itchavik', 'Tiññivik', 'Amiġaiqsivik', 'Sikkuvik', 'Nippivik', 'Siqiñġiḷaq'],
+ 'months_short' => ['Sñt', 'Sñs', 'Pan', 'Qil', 'Sup', 'Iġñ', 'Itc', 'Tiñ', 'Ami', 'Sik', 'Nip', 'Siq'],
+ 'weekdays' => ['Minġuiqsioiq', 'Savałłiq', 'Ilaqtchiioiq', 'Qitchiioiq', 'Sisamiioiq', 'Tallimmiioiq', 'Maqinġuoiq'],
+ 'weekdays_short' => ['Min', 'Sav', 'Ila', 'Qit', 'Sis', 'Tal', 'Maq'],
+ 'weekdays_min' => ['Min', 'Sav', 'Ila', 'Qit', 'Sis', 'Tal', 'Maq'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count ukiuq',
+ 'y' => ':count ukiuq',
+ 'a_year' => ':count ukiuq',
+
+ 'month' => ':count Tatqiat',
+ 'm' => ':count Tatqiat',
+ 'a_month' => ':count Tatqiat',
+
+ 'week' => ':count tatqiat', // less reliable
+ 'w' => ':count tatqiat', // less reliable
+ 'a_week' => ':count tatqiat', // less reliable
+
+ 'day' => ':count siqiñiq', // less reliable
+ 'd' => ':count siqiñiq', // less reliable
+ 'a_day' => ':count siqiñiq', // less reliable
+
+ 'hour' => ':count Siḷa', // less reliable
+ 'h' => ':count Siḷa', // less reliable
+ 'a_hour' => ':count Siḷa', // less reliable
+
+ 'second' => ':count iġñiq', // less reliable
+ 's' => ':count iġñiq', // less reliable
+ 'a_second' => ':count iġñiq', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/in.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/in.php
new file mode 100644
index 0000000..406112a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/in.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/id.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/is.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/is.php
new file mode 100644
index 0000000..9990168
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/is.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kristján Ingi Geirsson
+ */
+return [
+ 'year' => '1 ár|:count ár',
+ 'y' => '1 ár|:count ár',
+ 'month' => '1 mánuður|:count mánuðir',
+ 'm' => '1 mánuður|:count mánuðir',
+ 'week' => '1 vika|:count vikur',
+ 'w' => '1 vika|:count vikur',
+ 'day' => '1 dagur|:count dagar',
+ 'd' => '1 dagur|:count dagar',
+ 'hour' => '1 klukkutími|:count klukkutímar',
+ 'h' => '1 klukkutími|:count klukkutímar',
+ 'minute' => '1 mínúta|:count mínútur',
+ 'min' => '1 mínúta|:count mínútur',
+ 'second' => '1 sekúnda|:count sekúndur',
+ 's' => '1 sekúnda|:count sekúndur',
+ 'ago' => ':time síðan',
+ 'from_now' => ':time síðan',
+ 'after' => ':time eftir',
+ 'before' => ':time fyrir',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' og '],
+ 'meridiem' => ['fh', 'eh'],
+ 'diff_now' => 'núna',
+ 'diff_yesterday' => 'í gær',
+ 'diff_tomorrow' => 'á morgun',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM [kl.] HH:mm',
+ 'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm',
+ ],
+ 'weekdays' => ['sunnudaginn', 'mánudaginn', 'þriðjudaginn', 'miðvikudaginn', 'fimmtudaginn', 'föstudaginn', 'laugardaginn'],
+ 'weekdays_short' => ['sun', 'mán', 'þri', 'mið', 'fim', 'fös', 'lau'],
+ 'weekdays_min' => ['sun', 'mán', 'þri', 'mið', 'fim', 'fös', 'lau'],
+ 'months' => ['janúar', 'febrúar', 'mars', 'apríl', 'maí', 'júní', 'júlí', 'ágúst', 'september', 'október', 'nóvember', 'desember'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maí', 'jún', 'júl', 'ágú', 'sep', 'okt', 'nóv', 'des'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/is_IS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/is_IS.php
new file mode 100644
index 0000000..8b91bb2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/is_IS.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/is.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it.php
new file mode 100644
index 0000000..c23d8db
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it.php
@@ -0,0 +1,103 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ash
+ * - François B
+ * - Marco Perrando
+ * - Massimiliano Caniparoli
+ * - JD Isaacks
+ * - Andrea Martini
+ * - Francesco Marasco
+ * - Tizianoz93
+ * - Davide Casiraghi (davide-casiraghi)
+ * - Pete Scopes (pdscopes)
+ */
+return [
+ 'year' => ':count anno|:count anni',
+ 'a_year' => 'un anno|:count anni',
+ 'y' => ':count anno|:count anni',
+ 'month' => ':count mese|:count mesi',
+ 'a_month' => 'un mese|:count mesi',
+ 'm' => ':count mese|:count mesi',
+ 'week' => ':count settimana|:count settimane',
+ 'a_week' => 'una settimana|:count settimane',
+ 'w' => ':count set.',
+ 'day' => ':count giorno|:count giorni',
+ 'a_day' => 'un giorno|:count giorni',
+ 'd' => ':count g|:count gg',
+ 'hour' => ':count ora|:count ore',
+ 'a_hour' => 'un\'ora|:count ore',
+ 'h' => ':count h',
+ 'minute' => ':count minuto|:count minuti',
+ 'a_minute' => 'un minuto|:count minuti',
+ 'min' => ':count min.',
+ 'second' => ':count secondo|:count secondi',
+ 'a_second' => 'alcuni secondi|:count secondi',
+ 's' => ':count sec.',
+ 'millisecond' => ':count millisecondo|:count millisecondi',
+ 'a_millisecond' => 'un millisecondo|:count millisecondi',
+ 'ms' => ':countms',
+ 'microsecond' => ':count microsecondo|:count microsecondi',
+ 'a_microsecond' => 'un microsecondo|:count microsecondi',
+ 'µs' => ':countµs',
+ 'ago' => ':time fa',
+ 'from_now' => function ($time) {
+ return (preg_match('/^[0-9].+$/', $time) ? 'tra' : 'in')." $time";
+ },
+ 'after' => ':time dopo',
+ 'before' => ':time prima',
+ 'diff_now' => 'proprio ora',
+ 'diff_today' => 'Oggi',
+ 'diff_today_regexp' => 'Oggi(?:\\s+alle)?',
+ 'diff_yesterday' => 'ieri',
+ 'diff_yesterday_regexp' => 'Ieri(?:\\s+alle)?',
+ 'diff_tomorrow' => 'domani',
+ 'diff_tomorrow_regexp' => 'Domani(?:\\s+alle)?',
+ 'diff_before_yesterday' => 'l\'altro ieri',
+ 'diff_after_tomorrow' => 'dopodomani',
+ 'period_interval' => 'ogni :interval',
+ 'period_start_date' => 'dal :date',
+ 'period_end_date' => 'al :date',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Oggi alle] LT',
+ 'nextDay' => '[Domani alle] LT',
+ 'nextWeek' => 'dddd [alle] LT',
+ 'lastDay' => '[Ieri alle] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[la scorsa] dddd [alle] LT';
+ default:
+ return '[lo scorso] dddd [alle] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numberº',
+ 'months' => ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'],
+ 'months_short' => ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set', 'ott', 'nov', 'dic'],
+ 'weekdays' => ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato'],
+ 'weekdays_short' => ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
+ 'weekdays_min' => ['do', 'lu', 'ma', 'me', 'gi', 've', 'sa'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' e '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_CH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_CH.php
new file mode 100644
index 0000000..c23cc50
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_CH.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Propaganistas
+ */
+return array_replace_recursive(require __DIR__.'/it.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_IT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_IT.php
new file mode 100644
index 0000000..a5d1981
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_IT.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return require __DIR__.'/it.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_SM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_SM.php
new file mode 100644
index 0000000..57fab39
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_SM.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/it.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_VA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_VA.php
new file mode 100644
index 0000000..57fab39
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/it_VA.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/it.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/iu.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/iu.php
new file mode 100644
index 0000000..4fa9742
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/iu.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/iu_CA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/iu_CA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/iu_CA.php
new file mode 100644
index 0000000..6ab7e14
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/iu_CA.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Pablo Saratxaga pablo@mandriva.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'MM/DD/YY',
+ ],
+ 'months' => ['ᔮᓄᐊᓕ', 'ᕕᕗᐊᓕ', 'ᒪᔅᓯ', 'ᐃᐳᓗ', 'ᒪᐃ', 'ᔪᓂ', 'ᔪᓚᐃ', 'ᐊᒋᓯ', 'ᓯᑎᕙ', 'ᐊᑦᑐᕙ', 'ᓄᕕᕙ', 'ᑎᓯᕝᕙ'],
+ 'months_short' => ['ᔮᓄ', 'ᕕᕗ', 'ᒪᔅ', 'ᐃᐳ', 'ᒪᐃ', 'ᔪᓂ', 'ᔪᓚ', 'ᐊᒋ', 'ᓯᑎ', 'ᐊᑦ', 'ᓄᕕ', 'ᑎᓯ'],
+ 'weekdays' => ['ᓈᑦᑎᖑᔭᕐᕕᒃ', 'ᓇᒡᒐᔾᔭᐅ', 'ᓇᒡᒐᔾᔭᐅᓕᖅᑭᑦ', 'ᐱᖓᓲᓕᖅᓯᐅᑦ', 'ᕿᑎᖅᑰᑦ', 'ᐅᓪᓗᕈᓘᑐᐃᓇᖅ', 'ᓯᕙᑖᕕᒃ'],
+ 'weekdays_short' => ['ᓈ', 'ᓇ', 'ᓕ', 'ᐱ', 'ᕿ', 'ᐅ', 'ᓯ'],
+ 'weekdays_min' => ['ᓈ', 'ᓇ', 'ᓕ', 'ᐱ', 'ᕿ', 'ᐅ', 'ᓯ'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count ᐅᑭᐅᖅ',
+ 'y' => ':count ᐅᑭᐅᖅ',
+ 'a_year' => ':count ᐅᑭᐅᖅ',
+
+ 'month' => ':count qaammat',
+ 'm' => ':count qaammat',
+ 'a_month' => ':count qaammat',
+
+ 'week' => ':count sapaatip akunnera',
+ 'w' => ':count sapaatip akunnera',
+ 'a_week' => ':count sapaatip akunnera',
+
+ 'day' => ':count ulloq',
+ 'd' => ':count ulloq',
+ 'a_day' => ':count ulloq',
+
+ 'hour' => ':count ikarraq',
+ 'h' => ':count ikarraq',
+ 'a_hour' => ':count ikarraq',
+
+ 'minute' => ':count titiqqaralaaq', // less reliable
+ 'min' => ':count titiqqaralaaq', // less reliable
+ 'a_minute' => ':count titiqqaralaaq', // less reliable
+
+ 'second' => ':count marluk', // less reliable
+ 's' => ':count marluk', // less reliable
+ 'a_second' => ':count marluk', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/iw.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/iw.php
new file mode 100644
index 0000000..a8034e8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/iw.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'months' => ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'],
+ 'months_short' => ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳', 'דצמ׳'],
+ 'weekdays' => ['יום ראשון', 'יום שני', 'יום שלישי', 'יום רביעי', 'יום חמישי', 'יום שישי', 'יום שבת'],
+ 'weekdays_short' => ['יום א׳', 'יום ב׳', 'יום ג׳', 'יום ד׳', 'יום ה׳', 'יום ו׳', 'שבת'],
+ 'weekdays_min' => ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'],
+ 'meridiem' => ['לפנה״צ', 'אחה״צ'],
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'D.M.YYYY',
+ 'LL' => 'D בMMM YYYY',
+ 'LLL' => 'D בMMMM YYYY H:mm',
+ 'LLLL' => 'dddd, D בMMMM YYYY H:mm',
+ ],
+
+ 'year' => ':count שנה',
+ 'y' => ':count שנה',
+ 'a_year' => ':count שנה',
+
+ 'month' => ':count חודש',
+ 'm' => ':count חודש',
+ 'a_month' => ':count חודש',
+
+ 'week' => ':count שבוע',
+ 'w' => ':count שבוע',
+ 'a_week' => ':count שבוע',
+
+ 'day' => ':count יום',
+ 'd' => ':count יום',
+ 'a_day' => ':count יום',
+
+ 'hour' => ':count שעה',
+ 'h' => ':count שעה',
+ 'a_hour' => ':count שעה',
+
+ 'minute' => ':count דקה',
+ 'min' => ':count דקה',
+ 'a_minute' => ':count דקה',
+
+ 'second' => ':count שניה',
+ 's' => ':count שניה',
+ 'a_second' => ':count שניה',
+
+ 'ago' => 'לפני :time',
+ 'from_now' => 'בעוד :time',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ja.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ja.php
new file mode 100644
index 0000000..fa4cb36
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ja.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Takuya Sawada
+ * - Atsushi Tanaka
+ * - François B
+ * - Jason Katz-Brown
+ * - Serhan Apaydın
+ * - XueWei
+ * - JD Isaacks
+ * - toyama satoshi
+ * - atakigawa
+ */
+return [
+ 'year' => ':count年',
+ 'y' => ':count年',
+ 'month' => ':countヶ月',
+ 'm' => ':countヶ月',
+ 'week' => ':count週間',
+ 'w' => ':count週間',
+ 'day' => ':count日',
+ 'd' => ':count日',
+ 'hour' => ':count時間',
+ 'h' => ':count時間',
+ 'minute' => ':count分',
+ 'min' => ':count分',
+ 'second' => ':count秒',
+ 'a_second' => '{1}数秒|]1,Inf[:count秒',
+ 's' => ':count秒',
+ 'ago' => ':time前',
+ 'from_now' => ':time後',
+ 'after' => ':time後',
+ 'before' => ':time前',
+ 'diff_now' => '今',
+ 'diff_today' => '今日',
+ 'diff_yesterday' => '昨日',
+ 'diff_tomorrow' => '明日',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY/MM/DD',
+ 'LL' => 'YYYY年M月D日',
+ 'LLL' => 'YYYY年M月D日 HH:mm',
+ 'LLLL' => 'YYYY年M月D日 dddd HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[今日] LT',
+ 'nextDay' => '[明日] LT',
+ 'nextWeek' => function (\Carbon\CarbonInterface $current, \Carbon\CarbonInterface $other) {
+ if ($other->week !== $current->week) {
+ return '[来週]dddd LT';
+ }
+
+ return 'dddd LT';
+ },
+ 'lastDay' => '[昨日] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $current, \Carbon\CarbonInterface $other) {
+ if ($other->week !== $current->week) {
+ return '[先週]dddd LT';
+ }
+
+ return 'dddd LT';
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return $number.'日';
+ default:
+ return $number;
+ }
+ },
+ 'meridiem' => ['午前', '午後'],
+ 'months' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+ 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+ 'weekdays' => ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'],
+ 'weekdays_short' => ['日', '月', '火', '水', '木', '金', '土'],
+ 'weekdays_min' => ['日', '月', '火', '水', '木', '金', '土'],
+ 'list' => '、',
+ 'alt_numbers' => ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', '二十一', '二十二', '二十三', '二十四', '二十五', '二十六', '二十七', '二十八', '二十九', '三十', '三十一', '三十二', '三十三', '三十四', '三十五', '三十六', '三十七', '三十八', '三十九', '四十', '四十一', '四十二', '四十三', '四十四', '四十五', '四十六', '四十七', '四十八', '四十九', '五十', '五十一', '五十二', '五十三', '五十四', '五十五', '五十六', '五十七', '五十八', '五十九', '六十', '六十一', '六十二', '六十三', '六十四', '六十五', '六十六', '六十七', '六十八', '六十九', '七十', '七十一', '七十二', '七十三', '七十四', '七十五', '七十六', '七十七', '七十八', '七十九', '八十', '八十一', '八十二', '八十三', '八十四', '八十五', '八十六', '八十七', '八十八', '八十九', '九十', '九十一', '九十二', '九十三', '九十四', '九十五', '九十六', '九十七', '九十八', '九十九'],
+ 'alt_numbers_pow' => [
+ 10000 => '万',
+ 1000 => '千',
+ 100 => '百',
+ ],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ja_JP.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ja_JP.php
new file mode 100644
index 0000000..9e035fd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ja_JP.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ja.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/jgo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/jgo.php
new file mode 100644
index 0000000..bad6beb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/jgo.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/jmc.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/jmc.php
new file mode 100644
index 0000000..f8cc72c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/jmc.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['utuko', 'kyiukonyi'],
+ 'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
+ 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/jv.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/jv.php
new file mode 100644
index 0000000..bcbe044
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/jv.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - tgfjt
+ * - JD Isaacks
+ */
+return [
+ 'year' => '{1}setaun|]1,Inf[:count taun',
+ 'month' => '{1}sewulan|]1,Inf[:count wulan',
+ 'week' => '{1}sakminggu|]1,Inf[:count minggu',
+ 'day' => '{1}sedinten|]1,Inf[:count dinten',
+ 'hour' => '{1}setunggal jam|]1,Inf[:count jam',
+ 'minute' => '{1}setunggal menit|]1,Inf[:count menit',
+ 'second' => '{1}sawetawis detik|]1,Inf[:count detik',
+ 'ago' => ':time ingkang kepengker',
+ 'from_now' => 'wonten ing :time',
+ 'diff_today' => 'Dinten',
+ 'diff_yesterday' => 'Kala',
+ 'diff_yesterday_regexp' => 'Kala(?:\\s+wingi)?(?:\\s+pukul)?',
+ 'diff_tomorrow' => 'Mbenjang',
+ 'diff_tomorrow_regexp' => 'Mbenjang(?:\\s+pukul)?',
+ 'diff_today_regexp' => 'Dinten(?:\\s+puniko)?(?:\\s+pukul)?',
+ 'formats' => [
+ 'LT' => 'HH.mm',
+ 'LTS' => 'HH.mm.ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY [pukul] HH.mm',
+ 'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Dinten puniko pukul] LT',
+ 'nextDay' => '[Mbenjang pukul] LT',
+ 'nextWeek' => 'dddd [pukul] LT',
+ 'lastDay' => '[Kala wingi pukul] LT',
+ 'lastWeek' => 'dddd [kepengker pukul] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour) {
+ if ($hour < 11) {
+ return 'enjing';
+ }
+ if ($hour < 15) {
+ return 'siyang';
+ }
+ if ($hour < 19) {
+ return 'sonten';
+ }
+
+ return 'ndalu';
+ },
+ 'months' => ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'Nopember', 'Desember'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ags', 'Sep', 'Okt', 'Nop', 'Des'],
+ 'weekdays' => ['Minggu', 'Senen', 'Seloso', 'Rebu', 'Kemis', 'Jemuwah', 'Septu'],
+ 'weekdays_short' => ['Min', 'Sen', 'Sel', 'Reb', 'Kem', 'Jem', 'Sep'],
+ 'weekdays_min' => ['Mg', 'Sn', 'Sl', 'Rb', 'Km', 'Jm', 'Sp'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' lan '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ka.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ka.php
new file mode 100644
index 0000000..5ddb957
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ka.php
@@ -0,0 +1,201 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Tornike Razmadze
+ * - François B
+ * - Lasha Dolidze
+ * - Tim Fish
+ * - JD Isaacks
+ * - Tornike Razmadze
+ * - François B
+ * - Lasha Dolidze
+ * - JD Isaacks
+ * - LONGMAN
+ * - Avtandil Kikabidze (akalongman)
+ * - Levan Velijanashvili (Stichoza)
+ */
+return [
+ 'year' => ':count წელი',
+ 'y' => ':count წელი',
+ 'a_year' => '{1}წელი|]1,Inf[:count წელი',
+ 'month' => ':count თვე',
+ 'm' => ':count თვე',
+ 'a_month' => '{1}თვე|]1,Inf[:count თვე',
+ 'week' => ':count კვირა',
+ 'w' => ':count კვირა',
+ 'a_week' => '{1}კვირა|]1,Inf[:count კვირა',
+ 'day' => ':count დღე',
+ 'd' => ':count დღე',
+ 'a_day' => '{1}დღე|]1,Inf[:count დღე',
+ 'hour' => ':count საათი',
+ 'h' => ':count საათი',
+ 'a_hour' => '{1}საათი|]1,Inf[:count საათი',
+ 'minute' => ':count წუთი',
+ 'min' => ':count წუთი',
+ 'a_minute' => '{1}წუთი|]1,Inf[:count წუთი',
+ 'second' => ':count წამი',
+ 's' => ':count წამი',
+ 'a_second' => '{1}რამდენიმე წამი|]1,Inf[:count წამი',
+ 'ago' => function ($time) {
+ $replacements = [
+ // year
+ 'წელი' => 'წლის',
+ // month
+ 'თვე' => 'თვის',
+ // week
+ 'კვირა' => 'კვირის',
+ // day
+ 'დღე' => 'დღის',
+ // hour
+ 'საათი' => 'საათის',
+ // minute
+ 'წუთი' => 'წუთის',
+ // second
+ 'წამი' => 'წამის',
+ ];
+ $time = strtr($time, array_flip($replacements));
+ $time = strtr($time, $replacements);
+
+ return "$time წინ";
+ },
+ 'from_now' => function ($time) {
+ $replacements = [
+ // year
+ 'წელი' => 'წელიწადში',
+ // week
+ 'კვირა' => 'კვირაში',
+ // day
+ 'დღე' => 'დღეში',
+ // month
+ 'თვე' => 'თვეში',
+ // hour
+ 'საათი' => 'საათში',
+ // minute
+ 'წუთი' => 'წუთში',
+ // second
+ 'წამი' => 'წამში',
+ ];
+ $time = strtr($time, array_flip($replacements));
+ $time = strtr($time, $replacements);
+
+ return $time;
+ },
+ 'after' => function ($time) {
+ $replacements = [
+ // year
+ 'წელი' => 'წლის',
+ // month
+ 'თვე' => 'თვის',
+ // week
+ 'კვირა' => 'კვირის',
+ // day
+ 'დღე' => 'დღის',
+ // hour
+ 'საათი' => 'საათის',
+ // minute
+ 'წუთი' => 'წუთის',
+ // second
+ 'წამი' => 'წამის',
+ ];
+ $time = strtr($time, array_flip($replacements));
+ $time = strtr($time, $replacements);
+
+ return "$time შემდეგ";
+ },
+ 'before' => function ($time) {
+ $replacements = [
+ // year
+ 'წელი' => 'წლით',
+ // month
+ 'თვე' => 'თვით',
+ // week
+ 'კვირა' => 'კვირით',
+ // day
+ 'დღე' => 'დღით',
+ // hour
+ 'საათი' => 'საათით',
+ // minute
+ 'წუთი' => 'წუთით',
+ // second
+ 'წამი' => 'წამით',
+ ];
+ $time = strtr($time, array_flip($replacements));
+ $time = strtr($time, $replacements);
+
+ return "$time ადრე";
+ },
+ 'diff_now' => 'ახლა',
+ 'diff_today' => 'დღეს',
+ 'diff_yesterday' => 'გუშინ',
+ 'diff_tomorrow' => 'ხვალ',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[დღეს], LT[-ზე]',
+ 'nextDay' => '[ხვალ], LT[-ზე]',
+ 'nextWeek' => function (\Carbon\CarbonInterface $current, \Carbon\CarbonInterface $other) {
+ return ($current->isSameWeek($other) ? '' : '[შემდეგ] ').'dddd, LT[-ზე]';
+ },
+ 'lastDay' => '[გუშინ], LT[-ზე]',
+ 'lastWeek' => '[წინა] dddd, LT-ზე',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ if ($number === 0) {
+ return $number;
+ }
+ if ($number === 1) {
+ return $number.'-ლი';
+ }
+ if (($number < 20) || ($number <= 100 && ($number % 20 === 0)) || ($number % 100 === 0)) {
+ return 'მე-'.$number;
+ }
+
+ return $number.'-ე';
+ },
+ 'months' => ['იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი', 'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'],
+ 'months_standalone' => ['იანვარს', 'თებერვალს', 'მარტს', 'აპრილს', 'მაისს', 'ივნისს', 'ივლისს', 'აგვისტოს', 'სექტემბერს', 'ოქტომბერს', 'ნოემბერს', 'დეკემბერს'],
+ 'months_short' => ['იან', 'თებ', 'მარ', 'აპრ', 'მაი', 'ივნ', 'ივლ', 'აგვ', 'სექ', 'ოქტ', 'ნოე', 'დეკ'],
+ 'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
+ 'weekdays' => ['კვირას', 'ორშაბათს', 'სამშაბათს', 'ოთხშაბათს', 'ხუთშაბათს', 'პარასკევს', 'შაბათს'],
+ 'weekdays_standalone' => ['კვირა', 'ორშაბათი', 'სამშაბათი', 'ოთხშაბათი', 'ხუთშაბათი', 'პარასკევი', 'შაბათი'],
+ 'weekdays_short' => ['კვი', 'ორშ', 'სამ', 'ოთხ', 'ხუთ', 'პარ', 'შაბ'],
+ 'weekdays_min' => ['კვ', 'ორ', 'სა', 'ოთ', 'ხუ', 'პა', 'შა'],
+ 'weekdays_regexp' => '/^([^d].*|.*[^d])$/',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' და '],
+ 'meridiem' => function ($hour) {
+ if ($hour >= 4) {
+ if ($hour < 11) {
+ return 'დილის';
+ }
+
+ if ($hour < 16) {
+ return 'შუადღის';
+ }
+
+ if ($hour < 22) {
+ return 'საღამოს';
+ }
+ }
+
+ return 'ღამის';
+ },
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ka_GE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ka_GE.php
new file mode 100644
index 0000000..dd77fa3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ka_GE.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ka.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kab.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kab.php
new file mode 100644
index 0000000..94d6473
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kab.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/kab_DZ.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kab_DZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kab_DZ.php
new file mode 100644
index 0000000..796660b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kab_DZ.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - belkacem77@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Yennayer', 'Fuṛar', 'Meɣres', 'Yebrir', 'Mayyu', 'Yunyu', 'Yulyu', 'ɣuct', 'Ctembeṛ', 'Tubeṛ', 'Wambeṛ', 'Dujembeṛ'],
+ 'months_short' => ['Yen', 'Fur', 'Meɣ', 'Yeb', 'May', 'Yun', 'Yul', 'ɣuc', 'Cte', 'Tub', 'Wam', 'Duj'],
+ 'weekdays' => ['Acer', 'Arim', 'Aram', 'Ahad', 'Amhad', 'Sem', 'Sed'],
+ 'weekdays_short' => ['Ace', 'Ari', 'Ara', 'Aha', 'Amh', 'Sem', 'Sed'],
+ 'weekdays_min' => ['Ace', 'Ari', 'Ara', 'Aha', 'Amh', 'Sem', 'Sed'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['FT', 'MD'],
+
+ 'year' => ':count n yiseggasen',
+ 'y' => ':count n yiseggasen',
+ 'a_year' => ':count n yiseggasen',
+
+ 'month' => ':count n wayyuren',
+ 'm' => ':count n wayyuren',
+ 'a_month' => ':count n wayyuren',
+
+ 'week' => ':count n ledwaṛ', // less reliable
+ 'w' => ':count n ledwaṛ', // less reliable
+ 'a_week' => ':count n ledwaṛ', // less reliable
+
+ 'day' => ':count n wussan',
+ 'd' => ':count n wussan',
+ 'a_day' => ':count n wussan',
+
+ 'hour' => ':count n tsaɛtin',
+ 'h' => ':count n tsaɛtin',
+ 'a_hour' => ':count n tsaɛtin',
+
+ 'minute' => ':count n tedqiqin',
+ 'min' => ':count n tedqiqin',
+ 'a_minute' => ':count n tedqiqin',
+
+ 'second' => ':count tasdidt', // less reliable
+ 's' => ':count tasdidt', // less reliable
+ 'a_second' => ':count tasdidt', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kam.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kam.php
new file mode 100644
index 0000000..0fb6b2e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kam.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Ĩyakwakya', 'Ĩyawĩoo'],
+ 'weekdays' => ['Wa kyumwa', 'Wa kwambĩlĩlya', 'Wa kelĩ', 'Wa katatũ', 'Wa kana', 'Wa katano', 'Wa thanthatũ'],
+ 'weekdays_short' => ['Wky', 'Wkw', 'Wkl', 'Wtũ', 'Wkn', 'Wtn', 'Wth'],
+ 'weekdays_min' => ['Wky', 'Wkw', 'Wkl', 'Wtũ', 'Wkn', 'Wtn', 'Wth'],
+ 'months' => ['Mwai wa mbee', 'Mwai wa kelĩ', 'Mwai wa katatũ', 'Mwai wa kana', 'Mwai wa katano', 'Mwai wa thanthatũ', 'Mwai wa muonza', 'Mwai wa nyaanya', 'Mwai wa kenda', 'Mwai wa ĩkumi', 'Mwai wa ĩkumi na ĩmwe', 'Mwai wa ĩkumi na ilĩ'],
+ 'months_short' => ['Mbe', 'Kel', 'Ktũ', 'Kan', 'Ktn', 'Tha', 'Moo', 'Nya', 'Knd', 'Ĩku', 'Ĩkm', 'Ĩkl'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+
+ // Too unreliable
+ /*
+ 'year' => ':count mbua', // less reliable
+ 'y' => ':count mbua', // less reliable
+ 'a_year' => ':count mbua', // less reliable
+
+ 'month' => ':count ndakitali', // less reliable
+ 'm' => ':count ndakitali', // less reliable
+ 'a_month' => ':count ndakitali', // less reliable
+
+ 'day' => ':count wia', // less reliable
+ 'd' => ':count wia', // less reliable
+ 'a_day' => ':count wia', // less reliable
+
+ 'hour' => ':count orasan', // less reliable
+ 'h' => ':count orasan', // less reliable
+ 'a_hour' => ':count orasan', // less reliable
+
+ 'minute' => ':count orasan', // less reliable
+ 'min' => ':count orasan', // less reliable
+ 'a_minute' => ':count orasan', // less reliable
+ */
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kde.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kde.php
new file mode 100644
index 0000000..8acdaba
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kde.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Muhi', 'Chilo'],
+ 'weekdays' => ['Liduva lyapili', 'Liduva lyatatu', 'Liduva lyanchechi', 'Liduva lyannyano', 'Liduva lyannyano na linji', 'Liduva lyannyano na mavili', 'Liduva litandi'],
+ 'weekdays_short' => ['Ll2', 'Ll3', 'Ll4', 'Ll5', 'Ll6', 'Ll7', 'Ll1'],
+ 'weekdays_min' => ['Ll2', 'Ll3', 'Ll4', 'Ll5', 'Ll6', 'Ll7', 'Ll1'],
+ 'months' => ['Mwedi Ntandi', 'Mwedi wa Pili', 'Mwedi wa Tatu', 'Mwedi wa Nchechi', 'Mwedi wa Nnyano', 'Mwedi wa Nnyano na Umo', 'Mwedi wa Nnyano na Mivili', 'Mwedi wa Nnyano na Mitatu', 'Mwedi wa Nnyano na Nchechi', 'Mwedi wa Nnyano na Nnyano', 'Mwedi wa Nnyano na Nnyano na U', 'Mwedi wa Nnyano na Nnyano na M'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kea.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kea.php
new file mode 100644
index 0000000..8a334e2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kea.php
@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['a', 'p'],
+ 'weekdays' => ['dumingu', 'sigunda-fera', 'tersa-fera', 'kuarta-fera', 'kinta-fera', 'sesta-fera', 'sabadu'],
+ 'weekdays_short' => ['dum', 'sig', 'ter', 'kua', 'kin', 'ses', 'sab'],
+ 'weekdays_min' => ['du', 'si', 'te', 'ku', 'ki', 'se', 'sa'],
+ 'weekdays_standalone' => ['dumingu', 'sigunda-fera', 'tersa-fera', 'kuarta-fera', 'kinta-fera', 'sesta-fera', 'sábadu'],
+ 'months' => ['Janeru', 'Febreru', 'Marsu', 'Abril', 'Maiu', 'Junhu', 'Julhu', 'Agostu', 'Setenbru', 'Otubru', 'Nuvenbru', 'Dizenbru'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Otu', 'Nuv', 'Diz'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D [di] MMMM [di] YYYY HH:mm',
+ 'LLLL' => 'dddd, D [di] MMMM [di] YYYY HH:mm',
+ ],
+
+ 'year' => ':count otunu', // less reliable
+ 'y' => ':count otunu', // less reliable
+ 'a_year' => ':count otunu', // less reliable
+
+ 'week' => ':count día dumingu', // less reliable
+ 'w' => ':count día dumingu', // less reliable
+ 'a_week' => ':count día dumingu', // less reliable
+
+ 'day' => ':count diâ', // less reliable
+ 'd' => ':count diâ', // less reliable
+ 'a_day' => ':count diâ', // less reliable
+
+ 'minute' => ':count sugundu', // less reliable
+ 'min' => ':count sugundu', // less reliable
+ 'a_minute' => ':count sugundu', // less reliable
+
+ 'second' => ':count dós', // less reliable
+ 's' => ':count dós', // less reliable
+ 'a_second' => ':count dós', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/khq.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/khq.php
new file mode 100644
index 0000000..f0649e7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/khq.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Adduha', 'Aluula'],
+ 'weekdays' => ['Alhadi', 'Atini', 'Atalata', 'Alarba', 'Alhamiisa', 'Aljuma', 'Assabdu'],
+ 'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alj', 'Ass'],
+ 'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alj', 'Ass'],
+ 'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
+ 'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ki.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ki.php
new file mode 100644
index 0000000..5754ffc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ki.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Kiroko', 'Hwaĩ-inĩ'],
+ 'weekdays' => ['Kiumia', 'Njumatatũ', 'Njumaine', 'Njumatana', 'Aramithi', 'Njumaa', 'Njumamothi'],
+ 'weekdays_short' => ['KMA', 'NTT', 'NMN', 'NMT', 'ART', 'NMA', 'NMM'],
+ 'weekdays_min' => ['KMA', 'NTT', 'NMN', 'NMT', 'ART', 'NMA', 'NMM'],
+ 'months' => ['Njenuarĩ', 'Mwere wa kerĩ', 'Mwere wa gatatũ', 'Mwere wa kana', 'Mwere wa gatano', 'Mwere wa gatandatũ', 'Mwere wa mũgwanja', 'Mwere wa kanana', 'Mwere wa kenda', 'Mwere wa ikũmi', 'Mwere wa ikũmi na ũmwe', 'Ndithemba'],
+ 'months_short' => ['JEN', 'WKR', 'WGT', 'WKN', 'WTN', 'WTD', 'WMJ', 'WNN', 'WKD', 'WIK', 'WMW', 'DIT'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => ':count mĩaka', // less reliable
+ 'y' => ':count mĩaka', // less reliable
+ 'a_year' => ':count mĩaka', // less reliable
+
+ 'month' => ':count mweri', // less reliable
+ 'm' => ':count mweri', // less reliable
+ 'a_month' => ':count mweri', // less reliable
+
+ 'week' => ':count kiumia', // less reliable
+ 'w' => ':count kiumia', // less reliable
+ 'a_week' => ':count kiumia', // less reliable
+
+ 'day' => ':count mũthenya', // less reliable
+ 'd' => ':count mũthenya', // less reliable
+ 'a_day' => ':count mũthenya', // less reliable
+
+ 'hour' => ':count thaa', // less reliable
+ 'h' => ':count thaa', // less reliable
+ 'a_hour' => ':count thaa', // less reliable
+
+ 'minute' => ':count mundu', // less reliable
+ 'min' => ':count mundu', // less reliable
+ 'a_minute' => ':count mundu', // less reliable
+
+ 'second' => ':count igego', // less reliable
+ 's' => ':count igego', // less reliable
+ 'a_second' => ':count igego', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kk.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kk.php
new file mode 100644
index 0000000..59fa9af
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kk.php
@@ -0,0 +1,103 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - Talat Uspanov
+ * - Нурлан Рахимжанов
+ * - Toleugazy Kali
+ */
+return [
+ 'year' => ':count жыл',
+ 'a_year' => '{1}бір жыл|:count жыл',
+ 'y' => ':count ж.',
+ 'month' => ':count ай',
+ 'a_month' => '{1}бір ай|:count ай',
+ 'm' => ':count ай',
+ 'week' => ':count апта',
+ 'a_week' => '{1}бір апта',
+ 'w' => ':count ап.',
+ 'day' => ':count күн',
+ 'a_day' => '{1}бір күн|:count күн',
+ 'd' => ':count к.',
+ 'hour' => ':count сағат',
+ 'a_hour' => '{1}бір сағат|:count сағат',
+ 'h' => ':count са.',
+ 'minute' => ':count минут',
+ 'a_minute' => '{1}бір минут|:count минут',
+ 'min' => ':count м.',
+ 'second' => ':count секунд',
+ 'a_second' => '{1}бірнеше секунд|:count секунд',
+ 's' => ':count се.',
+ 'ago' => ':time бұрын',
+ 'from_now' => ':time ішінде',
+ 'after' => ':time кейін',
+ 'before' => ':time бұрын',
+ 'diff_now' => 'қазір',
+ 'diff_today' => 'Бүгін',
+ 'diff_today_regexp' => 'Бүгін(?:\\s+сағат)?',
+ 'diff_yesterday' => 'кеше',
+ 'diff_yesterday_regexp' => 'Кеше(?:\\s+сағат)?',
+ 'diff_tomorrow' => 'ертең',
+ 'diff_tomorrow_regexp' => 'Ертең(?:\\s+сағат)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Бүгін сағат] LT',
+ 'nextDay' => '[Ертең сағат] LT',
+ 'nextWeek' => 'dddd [сағат] LT',
+ 'lastDay' => '[Кеше сағат] LT',
+ 'lastWeek' => '[Өткен аптаның] dddd [сағат] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ static $suffixes = [
+ 0 => '-ші',
+ 1 => '-ші',
+ 2 => '-ші',
+ 3 => '-ші',
+ 4 => '-ші',
+ 5 => '-ші',
+ 6 => '-шы',
+ 7 => '-ші',
+ 8 => '-ші',
+ 9 => '-шы',
+ 10 => '-шы',
+ 20 => '-шы',
+ 30 => '-шы',
+ 40 => '-шы',
+ 50 => '-ші',
+ 60 => '-шы',
+ 70 => '-ші',
+ 80 => '-ші',
+ 90 => '-шы',
+ 100 => '-ші',
+ ];
+
+ return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
+ },
+ 'months' => ['қаңтар', 'ақпан', 'наурыз', 'сәуір', 'мамыр', 'маусым', 'шілде', 'тамыз', 'қыркүйек', 'қазан', 'қараша', 'желтоқсан'],
+ 'months_short' => ['қаң', 'ақп', 'нау', 'сәу', 'мам', 'мау', 'шіл', 'там', 'қыр', 'қаз', 'қар', 'жел'],
+ 'weekdays' => ['жексенбі', 'дүйсенбі', 'сейсенбі', 'сәрсенбі', 'бейсенбі', 'жұма', 'сенбі'],
+ 'weekdays_short' => ['жек', 'дүй', 'сей', 'сәр', 'бей', 'жұм', 'сен'],
+ 'weekdays_min' => ['жк', 'дй', 'сй', 'ср', 'бй', 'жм', 'сн'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' және '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kk_KZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kk_KZ.php
new file mode 100644
index 0000000..af4a5b2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kk_KZ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/kk.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kkj.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kkj.php
new file mode 100644
index 0000000..bad6beb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kkj.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kl.php
new file mode 100644
index 0000000..7329a07
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kl.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/kl_GL.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kl_GL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kl_GL.php
new file mode 100644
index 0000000..4fed720
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kl_GL.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Danish Standards Association bug-glibc-locales@gnu.org
+ * - John Eyðstein Johannesen (mashema)
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd [d.] D. MMMM YYYY [kl.] HH:mm',
+ ],
+ 'months' => ['januaarip', 'februaarip', 'marsip', 'apriilip', 'maajip', 'juunip', 'juulip', 'aggustip', 'septembarip', 'oktobarip', 'novembarip', 'decembarip'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
+ 'weekdays' => ['sapaat', 'ataasinngorneq', 'marlunngorneq', 'pingasunngorneq', 'sisamanngorneq', 'tallimanngorneq', 'arfininngorneq'],
+ 'weekdays_short' => ['sap', 'ata', 'mar', 'pin', 'sis', 'tal', 'arf'],
+ 'weekdays_min' => ['sap', 'ata', 'mar', 'pin', 'sis', 'tal', 'arf'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => '{1}ukioq :count|{0}:count ukiut|]1,Inf[ukiut :count',
+ 'a_year' => '{1}ukioq|{0}:count ukiut|]1,Inf[ukiut :count',
+ 'y' => '{1}:countyr|{0}:countyrs|]1,Inf[:countyrs',
+
+ 'month' => '{1}qaammat :count|{0}:count qaammatit|]1,Inf[qaammatit :count',
+ 'a_month' => '{1}qaammat|{0}:count qaammatit|]1,Inf[qaammatit :count',
+ 'm' => '{1}:countmo|{0}:countmos|]1,Inf[:countmos',
+
+ 'week' => '{1}:count sap. ak.|{0}:count sap. ak.|]1,Inf[:count sap. ak.',
+ 'a_week' => '{1}a sap. ak.|{0}:count sap. ak.|]1,Inf[:count sap. ak.',
+ 'w' => ':countw',
+
+ 'day' => '{1}:count ulloq|{0}:count ullut|]1,Inf[:count ullut',
+ 'a_day' => '{1}a ulloq|{0}:count ullut|]1,Inf[:count ullut',
+ 'd' => ':countd',
+
+ 'hour' => '{1}:count tiimi|{0}:count tiimit|]1,Inf[:count tiimit',
+ 'a_hour' => '{1}tiimi|{0}:count tiimit|]1,Inf[:count tiimit',
+ 'h' => ':counth',
+
+ 'minute' => '{1}:count minutsi|{0}:count minutsit|]1,Inf[:count minutsit',
+ 'a_minute' => '{1}a minutsi|{0}:count minutsit|]1,Inf[:count minutsit',
+ 'min' => ':countm',
+
+ 'second' => '{1}:count sikunti|{0}:count sikuntit|]1,Inf[:count sikuntit',
+ 'a_second' => '{1}sikunti|{0}:count sikuntit|]1,Inf[:count sikuntit',
+ 's' => ':counts',
+
+ 'ago' => ':time matuma siorna',
+
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kln.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kln.php
new file mode 100644
index 0000000..b034ba5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kln.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['krn', 'koosk'],
+ 'weekdays' => ['Kotisap', 'Kotaai', 'Koaeng’', 'Kosomok', 'Koang’wan', 'Komuut', 'Kolo'],
+ 'weekdays_short' => ['Kts', 'Kot', 'Koo', 'Kos', 'Koa', 'Kom', 'Kol'],
+ 'weekdays_min' => ['Kts', 'Kot', 'Koo', 'Kos', 'Koa', 'Kom', 'Kol'],
+ 'months' => ['Mulgul', 'Ng’atyaato', 'Kiptaamo', 'Iwootkuut', 'Mamuut', 'Paagi', 'Ng’eiyeet', 'Rooptui', 'Bureet', 'Epeeso', 'Kipsuunde ne taai', 'Kipsuunde nebo aeng’'],
+ 'months_short' => ['Mul', 'Ngat', 'Taa', 'Iwo', 'Mam', 'Paa', 'Nge', 'Roo', 'Bur', 'Epe', 'Kpt', 'Kpa'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => ':count maghatiat', // less reliable
+ 'y' => ':count maghatiat', // less reliable
+ 'a_year' => ':count maghatiat', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/km.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/km.php
new file mode 100644
index 0000000..da790ac
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/km.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kruy Vanna
+ * - Sereysethy Touch
+ * - JD Isaacks
+ * - Sovichet Tep
+ */
+return [
+ 'year' => '{1}មួយឆ្នាំ|]1,Inf[:count ឆ្នាំ',
+ 'y' => ':count ឆ្នាំ',
+ 'month' => '{1}មួយខែ|]1,Inf[:count ខែ',
+ 'm' => ':count ខែ',
+ 'week' => ':count សប្ដាហ៍',
+ 'w' => ':count សប្ដាហ៍',
+ 'day' => '{1}មួយថ្ងៃ|]1,Inf[:count ថ្ងៃ',
+ 'd' => ':count ថ្ងៃ',
+ 'hour' => '{1}មួយម៉ោង|]1,Inf[:count ម៉ោង',
+ 'h' => ':count ម៉ោង',
+ 'minute' => '{1}មួយនាទី|]1,Inf[:count នាទី',
+ 'min' => ':count នាទី',
+ 'second' => '{1}ប៉ុន្មានវិនាទី|]1,Inf[:count វិនាទី',
+ 's' => ':count វិនាទី',
+ 'ago' => ':timeមុន',
+ 'from_now' => ':timeទៀត',
+ 'after' => 'នៅក្រោយ :time',
+ 'before' => 'នៅមុន :time',
+ 'diff_now' => 'ឥឡូវ',
+ 'diff_today' => 'ថ្ងៃនេះ',
+ 'diff_today_regexp' => 'ថ្ងៃនេះ(?:\\s+ម៉ោង)?',
+ 'diff_yesterday' => 'ម្សិលមិញ',
+ 'diff_yesterday_regexp' => 'ម្សិលមិញ(?:\\s+ម៉ោង)?',
+ 'diff_tomorrow' => 'ថ្ងៃស្អែក',
+ 'diff_tomorrow_regexp' => 'ស្អែក(?:\\s+ម៉ោង)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[ថ្ងៃនេះ ម៉ោង] LT',
+ 'nextDay' => '[ស្អែក ម៉ោង] LT',
+ 'nextWeek' => 'dddd [ម៉ោង] LT',
+ 'lastDay' => '[ម្សិលមិញ ម៉ោង] LT',
+ 'lastWeek' => 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => 'ទី:number',
+ 'meridiem' => ['ព្រឹក', 'ល្ងាច'],
+ 'months' => ['មករា', 'កុម្ភៈ', 'មីនា', 'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា', 'កញ្ញា', 'តុលា', 'វិច្ឆិកា', 'ធ្នូ'],
+ 'months_short' => ['មករា', 'កុម្ភៈ', 'មីនា', 'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា', 'កញ្ញា', 'តុលា', 'វិច្ឆិកា', 'ធ្នូ'],
+ 'weekdays' => ['អាទិត្យ', 'ច័ន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ', 'សៅរ៍'],
+ 'weekdays_short' => ['អា', 'ច', 'អ', 'ព', 'ព្រ', 'សុ', 'ស'],
+ 'weekdays_min' => ['អា', 'ច', 'អ', 'ព', 'ព្រ', 'សុ', 'ស'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', 'និង '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/km_KH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/km_KH.php
new file mode 100644
index 0000000..ef3b415
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/km_KH.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/km.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kn.php
new file mode 100644
index 0000000..0d2ad08
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kn.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - MOHAN M U
+ * - François B
+ * - rajeevnaikte
+ */
+return [
+ 'year' => '{1}ಒಂದು ವರ್ಷ|]1,Inf[:count ವರ್ಷ',
+ 'month' => '{1}ಒಂದು ತಿಂಗಳು|]1,Inf[:count ತಿಂಗಳು',
+ 'week' => '{1}ಒಂದು ವಾರ|]1,Inf[:count ವಾರಗಳು',
+ 'day' => '{1}ಒಂದು ದಿನ|]1,Inf[:count ದಿನ',
+ 'hour' => '{1}ಒಂದು ಗಂಟೆ|]1,Inf[:count ಗಂಟೆ',
+ 'minute' => '{1}ಒಂದು ನಿಮಿಷ|]1,Inf[:count ನಿಮಿಷ',
+ 'second' => '{1}ಕೆಲವು ಕ್ಷಣಗಳು|]1,Inf[:count ಸೆಕೆಂಡುಗಳು',
+ 'ago' => ':time ಹಿಂದೆ',
+ 'from_now' => ':time ನಂತರ',
+ 'diff_now' => 'ಈಗ',
+ 'diff_today' => 'ಇಂದು',
+ 'diff_yesterday' => 'ನಿನ್ನೆ',
+ 'diff_tomorrow' => 'ನಾಳೆ',
+ 'formats' => [
+ 'LT' => 'A h:mm',
+ 'LTS' => 'A h:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, A h:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY, A h:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[ಇಂದು] LT',
+ 'nextDay' => '[ನಾಳೆ] LT',
+ 'nextWeek' => 'dddd, LT',
+ 'lastDay' => '[ನಿನ್ನೆ] LT',
+ 'lastWeek' => '[ಕೊನೆಯ] dddd, LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numberನೇ',
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'ರಾತ್ರಿ';
+ }
+ if ($hour < 10) {
+ return 'ಬೆಳಿಗ್ಗೆ';
+ }
+ if ($hour < 17) {
+ return 'ಮಧ್ಯಾಹ್ನ';
+ }
+ if ($hour < 20) {
+ return 'ಸಂಜೆ';
+ }
+
+ return 'ರಾತ್ರಿ';
+ },
+ 'months' => ['ಜನವರಿ', 'ಫೆಬ್ರವರಿ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್', 'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್', 'ಡಿಸೆಂಬರ್'],
+ 'months_short' => ['ಜನ', 'ಫೆಬ್ರ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂ', 'ಅಕ್ಟೋ', 'ನವೆಂ', 'ಡಿಸೆಂ'],
+ 'weekdays' => ['ಭಾನುವಾರ', 'ಸೋಮವಾರ', 'ಮಂಗಳವಾರ', 'ಬುಧವಾರ', 'ಗುರುವಾರ', 'ಶುಕ್ರವಾರ', 'ಶನಿವಾರ'],
+ 'weekdays_short' => ['ಭಾನು', 'ಸೋಮ', 'ಮಂಗಳ', 'ಬುಧ', 'ಗುರು', 'ಶುಕ್ರ', 'ಶನಿ'],
+ 'weekdays_min' => ['ಭಾ', 'ಸೋ', 'ಮಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'],
+ 'list' => ', ',
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'weekend' => [0, 0],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kn_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kn_IN.php
new file mode 100644
index 0000000..7c6c909
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kn_IN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/kn.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ko.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ko.php
new file mode 100644
index 0000000..4fa6237
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ko.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kunal Marwaha
+ * - FourwingsY
+ * - François B
+ * - Jason Katz-Brown
+ * - Seokjun Kim
+ * - Junho Kim
+ * - JD Isaacks
+ * - Juwon Kim
+ */
+return [
+ 'year' => ':count년',
+ 'a_year' => '{1}일년|]1,Inf[:count년',
+ 'y' => ':count년',
+ 'month' => ':count개월',
+ 'a_month' => '{1}한달|]1,Inf[:count개월',
+ 'm' => ':count개월',
+ 'week' => ':count주',
+ 'a_week' => '{1}일주일|]1,Inf[:count 주',
+ 'w' => ':count주일',
+ 'day' => ':count일',
+ 'a_day' => '{1}하루|]1,Inf[:count일',
+ 'd' => ':count일',
+ 'hour' => ':count시간',
+ 'a_hour' => '{1}한시간|]1,Inf[:count시간',
+ 'h' => ':count시간',
+ 'minute' => ':count분',
+ 'a_minute' => '{1}일분|]1,Inf[:count분',
+ 'min' => ':count분',
+ 'second' => ':count초',
+ 'a_second' => '{1}몇초|]1,Inf[:count초',
+ 's' => ':count초',
+ 'ago' => ':time 전',
+ 'from_now' => ':time 후',
+ 'after' => ':time 후',
+ 'before' => ':time 전',
+ 'diff_now' => '지금',
+ 'diff_today' => '오늘',
+ 'diff_yesterday' => '어제',
+ 'diff_tomorrow' => '내일',
+ 'formats' => [
+ 'LT' => 'A h:mm',
+ 'LTS' => 'A h:mm:ss',
+ 'L' => 'YYYY.MM.DD.',
+ 'LL' => 'YYYY년 MMMM D일',
+ 'LLL' => 'YYYY년 MMMM D일 A h:mm',
+ 'LLLL' => 'YYYY년 MMMM D일 dddd A h:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '오늘 LT',
+ 'nextDay' => '내일 LT',
+ 'nextWeek' => 'dddd LT',
+ 'lastDay' => '어제 LT',
+ 'lastWeek' => '지난주 dddd LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return $number.'일';
+ case 'M':
+ return $number.'월';
+ case 'w':
+ case 'W':
+ return $number.'주';
+ default:
+ return $number;
+ }
+ },
+ 'meridiem' => ['오전', '오후'],
+ 'months' => ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
+ 'months_short' => ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
+ 'weekdays' => ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'],
+ 'weekdays_short' => ['일', '월', '화', '수', '목', '금', '토'],
+ 'weekdays_min' => ['일', '월', '화', '수', '목', '금', '토'],
+ 'list' => ' ',
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ko_KP.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ko_KP.php
new file mode 100644
index 0000000..55b40fa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ko_KP.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ko.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ko_KR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ko_KR.php
new file mode 100644
index 0000000..d8eba2c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ko_KR.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ko.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kok.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kok.php
new file mode 100644
index 0000000..4adcddc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kok.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/kok_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kok_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kok_IN.php
new file mode 100644
index 0000000..92ba844
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kok_IN.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Red Hat, Pune bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D-M-YY',
+ ],
+ 'months' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ओगस्ट', 'सेप्टेंबर', 'ओक्टोबर', 'नोव्हेंबर', 'डिसेंबर'],
+ 'months_short' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ओगस्ट', 'सेप्टेंबर', 'ओक्टोबर', 'नोव्हेंबर', 'डिसेंबर'],
+ 'weekdays' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'],
+ 'weekdays_short' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'],
+ 'weekdays_min' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['म.पू.', 'म.नं.'],
+
+ 'year' => ':count वैशाकु', // less reliable
+ 'y' => ':count वैशाकु', // less reliable
+ 'a_year' => ':count वैशाकु', // less reliable
+
+ 'week' => ':count आदित्यवार', // less reliable
+ 'w' => ':count आदित्यवार', // less reliable
+ 'a_week' => ':count आदित्यवार', // less reliable
+
+ 'minute' => ':count नोंद', // less reliable
+ 'min' => ':count नोंद', // less reliable
+ 'a_minute' => ':count नोंद', // less reliable
+
+ 'second' => ':count तेंको', // less reliable
+ 's' => ':count तेंको', // less reliable
+ 'a_second' => ':count तेंको', // less reliable
+
+ 'month' => ':count मैनो',
+ 'm' => ':count मैनो',
+ 'a_month' => ':count मैनो',
+
+ 'day' => ':count दिवसु',
+ 'd' => ':count दिवसु',
+ 'a_day' => ':count दिवसु',
+
+ 'hour' => ':count घंते',
+ 'h' => ':count घंते',
+ 'a_hour' => ':count घंते',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ks.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ks.php
new file mode 100644
index 0000000..9876079
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ks.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ks_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ks_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ks_IN.php
new file mode 100644
index 0000000..ce9d5d4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ks_IN.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Red Hat, Pune bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'M/D/YY',
+ ],
+ 'months' => ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل', 'میٔ', 'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر', 'اکتوٗبر', 'نومبر', 'دسمبر'],
+ 'months_short' => ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل', 'میٔ', 'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر', 'اکتوٗبر', 'نومبر', 'دسمبر'],
+ 'weekdays' => ['آتهوار', 'ژءندروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'],
+ 'weekdays_short' => ['آتهوار', 'ژءنتروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'],
+ 'weekdays_min' => ['آتهوار', 'ژءنتروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['دوپھربرونھ', 'دوپھرپتھ'],
+
+ 'year' => ':count آب', // less reliable
+ 'y' => ':count آب', // less reliable
+ 'a_year' => ':count آب', // less reliable
+
+ 'month' => ':count रान्', // less reliable
+ 'm' => ':count रान्', // less reliable
+ 'a_month' => ':count रान्', // less reliable
+
+ 'week' => ':count آتھٕوار', // less reliable
+ 'w' => ':count آتھٕوار', // less reliable
+ 'a_week' => ':count آتھٕوار', // less reliable
+
+ 'hour' => ':count سۄن', // less reliable
+ 'h' => ':count سۄن', // less reliable
+ 'a_hour' => ':count سۄن', // less reliable
+
+ 'minute' => ':count فَن', // less reliable
+ 'min' => ':count فَن', // less reliable
+ 'a_minute' => ':count فَن', // less reliable
+
+ 'second' => ':count दोʼयुम', // less reliable
+ 's' => ':count दोʼयुम', // less reliable
+ 'a_second' => ':count दोʼयुम', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ks_IN@devanagari.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ks_IN@devanagari.php
new file mode 100644
index 0000000..a2ae8b6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ks_IN@devanagari.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - ks-gnome-trans-commits@lists.code.indlinux.net
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'M/D/YY',
+ ],
+ 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
+ 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
+ 'weekdays' => ['आथवार', 'चॅ़दुरवार', 'बोमवार', 'ब्वदवार', 'ब्रसवार', 'शोकुरवार', 'बटुवार'],
+ 'weekdays_short' => ['आथ ', 'चॅ़दुर', 'बोम', 'ब्वद', 'ब्रस', 'शोकुर', 'बटु'],
+ 'weekdays_min' => ['आथ ', 'चॅ़दुर', 'बोम', 'ब्वद', 'ब्रस', 'शोकुर', 'बटु'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ksb.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ksb.php
new file mode 100644
index 0000000..424099d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ksb.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['makeo', 'nyiaghuo'],
+ 'weekdays' => ['Jumaapii', 'Jumaatatu', 'Jumaane', 'Jumaatano', 'Alhamisi', 'Ijumaa', 'Jumaamosi'],
+ 'weekdays_short' => ['Jpi', 'Jtt', 'Jmn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'weekdays_min' => ['Jpi', 'Jtt', 'Jmn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'months' => ['Januali', 'Febluali', 'Machi', 'Aplili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ksf.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ksf.php
new file mode 100644
index 0000000..8fb5598
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ksf.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['sárúwá', 'cɛɛ́nko'],
+ 'weekdays' => ['sɔ́ndǝ', 'lǝndí', 'maadí', 'mɛkrɛdí', 'jǝǝdí', 'júmbá', 'samdí'],
+ 'weekdays_short' => ['sɔ́n', 'lǝn', 'maa', 'mɛk', 'jǝǝ', 'júm', 'sam'],
+ 'weekdays_min' => ['sɔ́n', 'lǝn', 'maa', 'mɛk', 'jǝǝ', 'júm', 'sam'],
+ 'months' => ['ŋwíí a ntɔ́ntɔ', 'ŋwíí akǝ bɛ́ɛ', 'ŋwíí akǝ ráá', 'ŋwíí akǝ nin', 'ŋwíí akǝ táan', 'ŋwíí akǝ táafɔk', 'ŋwíí akǝ táabɛɛ', 'ŋwíí akǝ táaraa', 'ŋwíí akǝ táanin', 'ŋwíí akǝ ntɛk', 'ŋwíí akǝ ntɛk di bɔ́k', 'ŋwíí akǝ ntɛk di bɛ́ɛ'],
+ 'months_short' => ['ŋ1', 'ŋ2', 'ŋ3', 'ŋ4', 'ŋ5', 'ŋ6', 'ŋ7', 'ŋ8', 'ŋ9', 'ŋ10', 'ŋ11', 'ŋ12'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ksh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ksh.php
new file mode 100644
index 0000000..44c60a4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ksh.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['v.M.', 'n.M.'],
+ 'weekdays' => ['Sunndaach', 'Mohndaach', 'Dinnsdaach', 'Metwoch', 'Dunnersdaach', 'Friidaach', 'Samsdaach'],
+ 'weekdays_short' => ['Su.', 'Mo.', 'Di.', 'Me.', 'Du.', 'Fr.', 'Sa.'],
+ 'weekdays_min' => ['Su', 'Mo', 'Di', 'Me', 'Du', 'Fr', 'Sa'],
+ 'months' => ['Jannewa', 'Fäbrowa', 'Määz', 'Aprell', 'Mai', 'Juuni', 'Juuli', 'Oujoß', 'Septämber', 'Oktohber', 'Novämber', 'Dezämber'],
+ 'months_short' => ['Jan', 'Fäb', 'Mäz', 'Apr', 'Mai', 'Jun', 'Jul', 'Ouj', 'Säp', 'Okt', 'Nov', 'Dez'],
+ 'months_short_standalone' => ['Jan.', 'Fäb.', 'Mäz.', 'Apr.', 'Mai', 'Jun.', 'Jul.', 'Ouj.', 'Säp.', 'Okt.', 'Nov.', 'Dez.'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D. M. YYYY',
+ 'LL' => 'D. MMM. YYYY',
+ 'LLL' => 'D. MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, [dä] D. MMMM YYYY HH:mm',
+ ],
+
+ 'year' => ':count Johr',
+ 'y' => ':count Johr',
+ 'a_year' => ':count Johr',
+
+ 'month' => ':count Moohnd',
+ 'm' => ':count Moohnd',
+ 'a_month' => ':count Moohnd',
+
+ 'week' => ':count woch',
+ 'w' => ':count woch',
+ 'a_week' => ':count woch',
+
+ 'day' => ':count Daach',
+ 'd' => ':count Daach',
+ 'a_day' => ':count Daach',
+
+ 'hour' => ':count Uhr',
+ 'h' => ':count Uhr',
+ 'a_hour' => ':count Uhr',
+
+ 'minute' => ':count Menutt',
+ 'min' => ':count Menutt',
+ 'a_minute' => ':count Menutt',
+
+ 'second' => ':count Sekůndt',
+ 's' => ':count Sekůndt',
+ 'a_second' => ':count Sekůndt',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ku.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ku.php
new file mode 100644
index 0000000..b001e30
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ku.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Halwest Manguri
+ * - Kardo Qadir
+ */
+$months = ['کانونی دووەم', 'شوبات', 'ئازار', 'نیسان', 'ئایار', 'حوزەیران', 'تەمموز', 'ئاب', 'ئەیلول', 'تشرینی یەکەم', 'تشرینی دووەم', 'کانونی یەکەم'];
+
+$weekdays = ['دوو شەممە', 'سێ شەممە', 'چوار شەممە', 'پێنج شەممە', 'هەینی', 'شەممە', 'یەک شەممە'];
+
+return [
+ 'ago' => 'پێش :time',
+ 'from_now' => ':time لە ئێستاوە',
+ 'after' => 'دوای :time',
+ 'before' => 'پێش :time',
+ 'year' => '{0}ساڵ|{1}ساڵێک|{2}٢ ساڵ|[3,10]:count ساڵ|[11,Inf]:count ساڵ',
+ 'month' => '{0}مانگ|{1}مانگێک|{2}٢ مانگ|[3,10]:count مانگ|[11,Inf]:count مانگ',
+ 'week' => '{0}هەفتە|{1}هەفتەیەک|{2}٢ هەفتە|[3,10]:count هەفتە|[11,Inf]:count هەفتە',
+ 'day' => '{0}ڕۆژ|{1}ڕۆژێک|{2}٢ ڕۆژ|[3,10]:count ڕۆژ|[11,Inf]:count ڕۆژ',
+ 'hour' => '{0}کاتژمێر|{1}کاتژمێرێک|{2}٢ کاتژمێر|[3,10]:count کاتژمێر|[11,Inf]:count کاتژمێر',
+ 'minute' => '{0}خولەک|{1}خولەکێک|{2}٢ خولەک|[3,10]:count خولەک|[11,Inf]:count خولەک',
+ 'second' => '{0}چرکە|{1}چرکەیەک|{2}٢ چرکە|[3,10]:count چرکە|[11,Inf]:count چرکە',
+ 'months' => $months,
+ 'months_standalone' => $months,
+ 'months_short' => $months,
+ 'weekdays' => $weekdays,
+ 'weekdays_short' => $weekdays,
+ 'weekdays_min' => $weekdays,
+ 'list' => [', ', ' û '],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ku_TR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ku_TR.php
new file mode 100644
index 0000000..11fce2d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ku_TR.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ku.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kw.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kw.php
new file mode 100644
index 0000000..26e242e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kw.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/kw_GB.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kw_GB.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kw_GB.php
new file mode 100644
index 0000000..00bf52b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/kw_GB.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Alastair McKinstry bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['mis Genver', 'mis Hwevrer', 'mis Meurth', 'mis Ebrel', 'mis Me', 'mis Metheven', 'mis Gortheren', 'mis Est', 'mis Gwynngala', 'mis Hedra', 'mis Du', 'mis Kevardhu'],
+ 'months_short' => ['Gen', 'Hwe', 'Meu', 'Ebr', 'Me', 'Met', 'Gor', 'Est', 'Gwn', 'Hed', 'Du', 'Kev'],
+ 'weekdays' => ['De Sul', 'De Lun', 'De Merth', 'De Merher', 'De Yow', 'De Gwener', 'De Sadorn'],
+ 'weekdays_short' => ['Sul', 'Lun', 'Mth', 'Mhr', 'Yow', 'Gwe', 'Sad'],
+ 'weekdays_min' => ['Sul', 'Lun', 'Mth', 'Mhr', 'Yow', 'Gwe', 'Sad'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'year' => ':count bledhen',
+ 'y' => ':count bledhen',
+ 'a_year' => ':count bledhen',
+
+ 'month' => ':count mis',
+ 'm' => ':count mis',
+ 'a_month' => ':count mis',
+
+ 'week' => ':count seythen',
+ 'w' => ':count seythen',
+ 'a_week' => ':count seythen',
+
+ 'day' => ':count dydh',
+ 'd' => ':count dydh',
+ 'a_day' => ':count dydh',
+
+ 'hour' => ':count eur',
+ 'h' => ':count eur',
+ 'a_hour' => ':count eur',
+
+ 'minute' => ':count mynysen',
+ 'min' => ':count mynysen',
+ 'a_minute' => ':count mynysen',
+
+ 'second' => ':count pryjwyth',
+ 's' => ':count pryjwyth',
+ 'a_second' => ':count pryjwyth',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ky.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ky.php
new file mode 100644
index 0000000..e0d1af1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ky.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - acutexyz
+ * - Josh Soref
+ * - François B
+ * - Chyngyz Arystan uulu
+ * - Chyngyz
+ * - acutexyz
+ * - Josh Soref
+ * - François B
+ * - Chyngyz Arystan uulu
+ */
+return [
+ 'year' => ':count жыл',
+ 'a_year' => '{1}бир жыл|:count жыл',
+ 'y' => ':count жыл',
+ 'month' => ':count ай',
+ 'a_month' => '{1}бир ай|:count ай',
+ 'm' => ':count ай',
+ 'week' => ':count апта',
+ 'a_week' => '{1}бир апта|:count апта',
+ 'w' => ':count апт.',
+ 'day' => ':count күн',
+ 'a_day' => '{1}бир күн|:count күн',
+ 'd' => ':count күн',
+ 'hour' => ':count саат',
+ 'a_hour' => '{1}бир саат|:count саат',
+ 'h' => ':count саат.',
+ 'minute' => ':count мүнөт',
+ 'a_minute' => '{1}бир мүнөт|:count мүнөт',
+ 'min' => ':count мүн.',
+ 'second' => ':count секунд',
+ 'a_second' => '{1}бирнече секунд|:count секунд',
+ 's' => ':count сек.',
+ 'ago' => ':time мурун',
+ 'from_now' => ':time ичинде',
+ 'diff_now' => 'азыр',
+ 'diff_today' => 'Бүгүн',
+ 'diff_today_regexp' => 'Бүгүн(?:\\s+саат)?',
+ 'diff_yesterday' => 'кечээ',
+ 'diff_yesterday_regexp' => 'Кече(?:\\s+саат)?',
+ 'diff_tomorrow' => 'эртең',
+ 'diff_tomorrow_regexp' => 'Эртең(?:\\s+саат)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Бүгүн саат] LT',
+ 'nextDay' => '[Эртең саат] LT',
+ 'nextWeek' => 'dddd [саат] LT',
+ 'lastDay' => '[Кече саат] LT',
+ 'lastWeek' => '[Өткен аптанын] dddd [күнү] [саат] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ static $suffixes = [
+ 0 => '-чү',
+ 1 => '-чи',
+ 2 => '-чи',
+ 3 => '-чү',
+ 4 => '-чү',
+ 5 => '-чи',
+ 6 => '-чы',
+ 7 => '-чи',
+ 8 => '-чи',
+ 9 => '-чу',
+ 10 => '-чу',
+ 20 => '-чы',
+ 30 => '-чу',
+ 40 => '-чы',
+ 50 => '-чү',
+ 60 => '-чы',
+ 70 => '-чи',
+ 80 => '-чи',
+ 90 => '-чу',
+ 100 => '-чү',
+ ];
+
+ return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
+ },
+ 'months' => ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
+ 'months_short' => ['янв', 'фев', 'март', 'апр', 'май', 'июнь', 'июль', 'авг', 'сен', 'окт', 'ноя', 'дек'],
+ 'weekdays' => ['Жекшемби', 'Дүйшөмбү', 'Шейшемби', 'Шаршемби', 'Бейшемби', 'Жума', 'Ишемби'],
+ 'weekdays_short' => ['Жек', 'Дүй', 'Шей', 'Шар', 'Бей', 'Жум', 'Ише'],
+ 'weekdays_min' => ['Жк', 'Дй', 'Шй', 'Шр', 'Бй', 'Жм', 'Иш'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => ' ',
+ 'meridiem' => ['таңкы', 'түштөн кийинки'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ky_KG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ky_KG.php
new file mode 100644
index 0000000..4426bea
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ky_KG.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ky.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lag.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lag.php
new file mode 100644
index 0000000..dc959c9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lag.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['TOO', 'MUU'],
+ 'weekdays' => ['Jumapíiri', 'Jumatátu', 'Jumaíne', 'Jumatáano', 'Alamíisi', 'Ijumáa', 'Jumamóosi'],
+ 'weekdays_short' => ['Píili', 'Táatu', 'Íne', 'Táano', 'Alh', 'Ijm', 'Móosi'],
+ 'weekdays_min' => ['Píili', 'Táatu', 'Íne', 'Táano', 'Alh', 'Ijm', 'Móosi'],
+ 'months' => ['Kʉfúngatɨ', 'Kʉnaanɨ', 'Kʉkeenda', 'Kwiikumi', 'Kwiinyambála', 'Kwiidwaata', 'Kʉmʉʉnchɨ', 'Kʉvɨɨrɨ', 'Kʉsaatʉ', 'Kwiinyi', 'Kʉsaano', 'Kʉsasatʉ'],
+ 'months_short' => ['Fúngatɨ', 'Naanɨ', 'Keenda', 'Ikúmi', 'Inyambala', 'Idwaata', 'Mʉʉnchɨ', 'Vɨɨrɨ', 'Saatʉ', 'Inyi', 'Saano', 'Sasatʉ'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lb.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lb.php
new file mode 100644
index 0000000..db04834
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lb.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - Tsutomu Kuroda
+ * - dan-nl
+ * - Simon Lelorrain (slelorrain)
+ */
+return [
+ 'year' => ':count Joer',
+ 'y' => ':countJ',
+ 'month' => ':count Mount|:count Méint',
+ 'm' => ':countMo',
+ 'week' => ':count Woch|:count Wochen',
+ 'w' => ':countWo|:countWo',
+ 'day' => ':count Dag|:count Deeg',
+ 'd' => ':countD',
+ 'hour' => ':count Stonn|:count Stonnen',
+ 'h' => ':countSto',
+ 'minute' => ':count Minutt|:count Minutten',
+ 'min' => ':countM',
+ 'second' => ':count Sekonn|:count Sekonnen',
+ 's' => ':countSek',
+
+ 'ago' => 'virun :time',
+ 'from_now' => 'an :time',
+ 'before' => ':time virdrun',
+ 'after' => ':time duerno',
+
+ 'diff_today' => 'Haut',
+ 'diff_yesterday' => 'Gëschter',
+ 'diff_yesterday_regexp' => 'Gëschter(?:\\s+um)?',
+ 'diff_tomorrow' => 'Muer',
+ 'diff_tomorrow_regexp' => 'Muer(?:\\s+um)?',
+ 'diff_today_regexp' => 'Haut(?:\\s+um)?',
+ 'formats' => [
+ 'LT' => 'H:mm [Auer]',
+ 'LTS' => 'H:mm:ss [Auer]',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY H:mm [Auer]',
+ 'LLLL' => 'dddd, D. MMMM YYYY H:mm [Auer]',
+ ],
+
+ 'calendar' => [
+ 'sameDay' => '[Haut um] LT',
+ 'nextDay' => '[Muer um] LT',
+ 'nextWeek' => 'dddd [um] LT',
+ 'lastDay' => '[Gëschter um] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
+ switch ($date->dayOfWeek) {
+ case 2:
+ case 4:
+ return '[Leschten] dddd [um] LT';
+ default:
+ return '[Leschte] dddd [um] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+
+ 'months' => ['Januar', 'Februar', 'Mäerz', 'Abrëll', 'Mee', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
+ 'months_short' => ['Jan.', 'Febr.', 'Mrz.', 'Abr.', 'Mee', 'Jun.', 'Jul.', 'Aug.', 'Sept.', 'Okt.', 'Nov.', 'Dez.'],
+ 'weekdays' => ['Sonndeg', 'Méindeg', 'Dënschdeg', 'Mëttwoch', 'Donneschdeg', 'Freideg', 'Samschdeg'],
+ 'weekdays_short' => ['So.', 'Mé.', 'Dë.', 'Më.', 'Do.', 'Fr.', 'Sa.'],
+ 'weekdays_min' => ['So', 'Mé', 'Dë', 'Më', 'Do', 'Fr', 'Sa'],
+ 'ordinal' => ':number.',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' an '],
+ 'meridiem' => ['moies', 'mëttes'],
+ 'weekdays_short_standalone' => ['Son', 'Méi', 'Dën', 'Mët', 'Don', 'Fre', 'Sam'],
+ 'months_short_standalone' => ['Jan', 'Feb', 'Mäe', 'Abr', 'Mee', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lb_LU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lb_LU.php
new file mode 100644
index 0000000..c8625fe
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lb_LU.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/lb.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lg.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lg.php
new file mode 100644
index 0000000..48bc68b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lg.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/lg_UG.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lg_UG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lg_UG.php
new file mode 100644
index 0000000..aa02214
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lg_UG.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Akademe ya Luganda Kizito Birabwa kompyuta@kizito.uklinux.net
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi', 'Juuni', 'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul', 'Agu', 'Seb', 'Oki', 'Nov', 'Des'],
+ 'weekdays' => ['Sabiiti', 'Balaza', 'Lwakubiri', 'Lwakusatu', 'Lwakuna', 'Lwakutaano', 'Lwamukaaga'],
+ 'weekdays_short' => ['Sab', 'Bal', 'Lw2', 'Lw3', 'Lw4', 'Lw5', 'Lw6'],
+ 'weekdays_min' => ['Sab', 'Bal', 'Lw2', 'Lw3', 'Lw4', 'Lw5', 'Lw6'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'month' => ':count njuba', // less reliable
+ 'm' => ':count njuba', // less reliable
+ 'a_month' => ':count njuba', // less reliable
+
+ 'year' => ':count mwaaka',
+ 'y' => ':count mwaaka',
+ 'a_year' => ':count mwaaka',
+
+ 'week' => ':count sabbiiti',
+ 'w' => ':count sabbiiti',
+ 'a_week' => ':count sabbiiti',
+
+ 'day' => ':count lunaku',
+ 'd' => ':count lunaku',
+ 'a_day' => ':count lunaku',
+
+ 'hour' => 'saawa :count',
+ 'h' => 'saawa :count',
+ 'a_hour' => 'saawa :count',
+
+ 'minute' => 'ddakiika :count',
+ 'min' => 'ddakiika :count',
+ 'a_minute' => 'ddakiika :count',
+
+ 'second' => ':count kyʼokubiri',
+ 's' => ':count kyʼokubiri',
+ 'a_second' => ':count kyʼokubiri',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/li.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/li.php
new file mode 100644
index 0000000..86c3009
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/li.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/li_NL.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/li_NL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/li_NL.php
new file mode 100644
index 0000000..6c5feb7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/li_NL.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandriva.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['jannewarie', 'fibberwarie', 'miert', 'eprèl', 'meij', 'junie', 'julie', 'augustus', 'september', 'oktober', 'november', 'desember'],
+ 'months_short' => ['jan', 'fib', 'mie', 'epr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
+ 'weekdays' => ['zóndig', 'maondig', 'daensdig', 'goonsdig', 'dónderdig', 'vriedig', 'zaoterdig'],
+ 'weekdays_short' => ['zón', 'mao', 'dae', 'goo', 'dón', 'vri', 'zao'],
+ 'weekdays_min' => ['zón', 'mao', 'dae', 'goo', 'dón', 'vri', 'zao'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'minute' => ':count momênt', // less reliable
+ 'min' => ':count momênt', // less reliable
+ 'a_minute' => ':count momênt', // less reliable
+
+ 'year' => ':count jaor',
+ 'y' => ':count jaor',
+ 'a_year' => ':count jaor',
+
+ 'month' => ':count maond',
+ 'm' => ':count maond',
+ 'a_month' => ':count maond',
+
+ 'week' => ':count waek',
+ 'w' => ':count waek',
+ 'a_week' => ':count waek',
+
+ 'day' => ':count daag',
+ 'd' => ':count daag',
+ 'a_day' => ':count daag',
+
+ 'hour' => ':count oer',
+ 'h' => ':count oer',
+ 'a_hour' => ':count oer',
+
+ 'second' => ':count Secónd',
+ 's' => ':count Secónd',
+ 'a_second' => ':count Secónd',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lij.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lij.php
new file mode 100644
index 0000000..45732b5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lij.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/lij_IT.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lij_IT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lij_IT.php
new file mode 100644
index 0000000..f8726fd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lij_IT.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Gastaldi alessio.gastaldi@libero.it
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['zenâ', 'fevrâ', 'marzo', 'avrî', 'mazzo', 'zûgno', 'lûggio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dixembre'],
+ 'months_short' => ['zen', 'fev', 'mar', 'arv', 'maz', 'zûg', 'lûg', 'ago', 'set', 'ött', 'nov', 'dix'],
+ 'weekdays' => ['domenega', 'lûnedì', 'martedì', 'mercUrdì', 'zêggia', 'venardì', 'sabbo'],
+ 'weekdays_short' => ['dom', 'lûn', 'mar', 'mer', 'zêu', 'ven', 'sab'],
+ 'weekdays_min' => ['dom', 'lûn', 'mar', 'mer', 'zêu', 'ven', 'sab'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'year' => ':count etæ', // less reliable
+ 'y' => ':count etæ', // less reliable
+ 'a_year' => ':count etæ', // less reliable
+
+ 'month' => ':count meize',
+ 'm' => ':count meize',
+ 'a_month' => ':count meize',
+
+ 'week' => ':count settemannha',
+ 'w' => ':count settemannha',
+ 'a_week' => ':count settemannha',
+
+ 'day' => ':count giorno',
+ 'd' => ':count giorno',
+ 'a_day' => ':count giorno',
+
+ 'hour' => ':count reléuio', // less reliable
+ 'h' => ':count reléuio', // less reliable
+ 'a_hour' => ':count reléuio', // less reliable
+
+ 'minute' => ':count menûo',
+ 'min' => ':count menûo',
+ 'a_minute' => ':count menûo',
+
+ 'second' => ':count segondo',
+ 's' => ':count segondo',
+ 'a_second' => ':count segondo',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lkt.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lkt.php
new file mode 100644
index 0000000..968b058
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lkt.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+
+ 'month' => ':count haŋwí', // less reliable
+ 'm' => ':count haŋwí', // less reliable
+ 'a_month' => ':count haŋwí', // less reliable
+
+ 'week' => ':count šakówiŋ', // less reliable
+ 'w' => ':count šakówiŋ', // less reliable
+ 'a_week' => ':count šakówiŋ', // less reliable
+
+ 'hour' => ':count maza škaŋškaŋ', // less reliable
+ 'h' => ':count maza škaŋškaŋ', // less reliable
+ 'a_hour' => ':count maza škaŋškaŋ', // less reliable
+
+ 'minute' => ':count číkʼala', // less reliable
+ 'min' => ':count číkʼala', // less reliable
+ 'a_minute' => ':count číkʼala', // less reliable
+
+ 'year' => ':count waníyetu',
+ 'y' => ':count waníyetu',
+ 'a_year' => ':count waníyetu',
+
+ 'day' => ':count aŋpétu',
+ 'd' => ':count aŋpétu',
+ 'a_day' => ':count aŋpétu',
+
+ 'second' => ':count icinuŋpa',
+ 's' => ':count icinuŋpa',
+ 'a_second' => ':count icinuŋpa',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln.php
new file mode 100644
index 0000000..9d5c35d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ubuntu René Manassé GALEKWA renemanasse@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'months' => ['sánzá ya yambo', 'sánzá ya míbalé', 'sánzá ya mísáto', 'sánzá ya mínei', 'sánzá ya mítáno', 'sánzá ya motóbá', 'sánzá ya nsambo', 'sánzá ya mwambe', 'sánzá ya libwa', 'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́', 'sánzá ya zómi na míbalé'],
+ 'months_short' => ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul', 'agt', 'stb', 'ɔtb', 'nvb', 'dsb'],
+ 'weekdays' => ['Lomíngo', 'Mosálá mɔ̌kɔ́', 'Misálá míbalé', 'Misálá mísáto', 'Misálá mínei', 'Misálá mítáno', 'Mpɔ́sɔ'],
+ 'weekdays_short' => ['m1.', 'm2.', 'm3.', 'm4.', 'm5.', 'm6.', 'm7.'],
+ 'weekdays_min' => ['m1.', 'm2.', 'm3.', 'm4.', 'm5.', 'm6.', 'm7.'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => 'mbula :count',
+ 'y' => 'mbula :count',
+ 'a_year' => 'mbula :count',
+
+ 'month' => 'sánzá :count',
+ 'm' => 'sánzá :count',
+ 'a_month' => 'sánzá :count',
+
+ 'week' => 'mpɔ́sɔ :count',
+ 'w' => 'mpɔ́sɔ :count',
+ 'a_week' => 'mpɔ́sɔ :count',
+
+ 'day' => 'mokɔlɔ :count',
+ 'd' => 'mokɔlɔ :count',
+ 'a_day' => 'mokɔlɔ :count',
+
+ 'hour' => 'ngonga :count',
+ 'h' => 'ngonga :count',
+ 'a_hour' => 'ngonga :count',
+
+ 'minute' => 'miniti :count',
+ 'min' => 'miniti :count',
+ 'a_minute' => 'miniti :count',
+
+ 'second' => 'segɔnde :count',
+ 's' => 'segɔnde :count',
+ 'a_second' => 'segɔnde :count',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_AO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_AO.php
new file mode 100644
index 0000000..e244096
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_AO.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ln.php', [
+ 'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'],
+ 'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
+ 'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
+ 'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_CD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_CD.php
new file mode 100644
index 0000000..13635fc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_CD.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ubuntu René Manassé GALEKWA renemanasse@gmail.com
+ */
+return require __DIR__.'/ln.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_CF.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_CF.php
new file mode 100644
index 0000000..e244096
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_CF.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ln.php', [
+ 'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'],
+ 'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
+ 'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
+ 'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_CG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_CG.php
new file mode 100644
index 0000000..e244096
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ln_CG.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ln.php', [
+ 'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'],
+ 'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
+ 'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
+ 'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lo.php
new file mode 100644
index 0000000..48715f5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lo.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - ryanhart2
+ */
+return [
+ 'year' => ':count ປີ',
+ 'y' => ':count ປີ',
+ 'month' => ':count ເດືອນ',
+ 'm' => ':count ດ. ',
+ 'week' => ':count ອາທິດ',
+ 'w' => ':count ອທ. ',
+ 'day' => ':count ມື້',
+ 'd' => ':count ມື້',
+ 'hour' => ':count ຊົ່ວໂມງ',
+ 'h' => ':count ຊມ. ',
+ 'minute' => ':count ນາທີ',
+ 'min' => ':count ນທ. ',
+ 'second' => '{1}ບໍ່ເທົ່າໃດວິນາທີ|]1,Inf[:count ວິນາທີ',
+ 's' => ':count ວິ. ',
+ 'ago' => ':timeຜ່ານມາ',
+ 'from_now' => 'ອີກ :time',
+ 'diff_now' => 'ຕອນນີ້',
+ 'diff_today' => 'ມື້ນີ້ເວລາ',
+ 'diff_yesterday' => 'ມື້ວານນີ້ເວລາ',
+ 'diff_tomorrow' => 'ມື້ອື່ນເວລາ',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'ວັນdddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[ມື້ນີ້ເວລາ] LT',
+ 'nextDay' => '[ມື້ອື່ນເວລາ] LT',
+ 'nextWeek' => '[ວັນ]dddd[ໜ້າເວລາ] LT',
+ 'lastDay' => '[ມື້ວານນີ້ເວລາ] LT',
+ 'lastWeek' => '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => 'ທີ່:number',
+ 'meridiem' => ['ຕອນເຊົ້າ', 'ຕອນແລງ'],
+ 'months' => ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ', 'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ', 'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ', 'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'],
+ 'months_short' => ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ', 'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ', 'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ', 'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'],
+ 'weekdays' => ['ອາທິດ', 'ຈັນ', 'ອັງຄານ', 'ພຸດ', 'ພະຫັດ', 'ສຸກ', 'ເສົາ'],
+ 'weekdays_short' => ['ທິດ', 'ຈັນ', 'ອັງຄານ', 'ພຸດ', 'ພະຫັດ', 'ສຸກ', 'ເສົາ'],
+ 'weekdays_min' => ['ທ', 'ຈ', 'ອຄ', 'ພ', 'ພຫ', 'ສກ', 'ສ'],
+ 'list' => [', ', 'ແລະ '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lo_LA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lo_LA.php
new file mode 100644
index 0000000..c0a1d6b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lo_LA.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/lo.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lrc.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lrc.php
new file mode 100644
index 0000000..10661bb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lrc.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+
+ 'minute' => ':count هنر', // less reliable
+ 'min' => ':count هنر', // less reliable
+ 'a_minute' => ':count هنر', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lrc_IQ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lrc_IQ.php
new file mode 100644
index 0000000..449d863
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lrc_IQ.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/lrc.php', [
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lt.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lt.php
new file mode 100644
index 0000000..7d1b6f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lt.php
@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - Tsutomu Kuroda
+ * - tjku
+ * - valdas406
+ * - Justas Palumickas
+ * - Max Melentiev
+ * - Andrius Janauskas
+ * - Juanito Fatas
+ * - Akira Matsuda
+ * - Christopher Dell
+ * - Enrique Vidal
+ * - Simone Carletti
+ * - Aaron Patterson
+ * - Nicolás Hock Isaza
+ * - Laurynas Butkus
+ * - Sven Fuchs
+ * - Dominykas Tijūnaitis
+ * - Justinas Bolys
+ * - Ričardas
+ * - Kirill Chalkin
+ * - Rolandas
+ * - Justinas (Gamesh)
+ */
+return [
+ 'year' => ':count metai|:count metai|:count metų',
+ 'y' => ':count m.',
+ 'month' => ':count mėnuo|:count mėnesiai|:count mėnesį',
+ 'm' => ':count mėn.',
+ 'week' => ':count savaitė|:count savaitės|:count savaitę',
+ 'w' => ':count sav.',
+ 'day' => ':count diena|:count dienos|:count dienų',
+ 'd' => ':count d.',
+ 'hour' => ':count valanda|:count valandos|:count valandų',
+ 'h' => ':count val.',
+ 'minute' => ':count minutė|:count minutės|:count minutę',
+ 'min' => ':count min.',
+ 'second' => ':count sekundė|:count sekundės|:count sekundžių',
+ 's' => ':count sek.',
+
+ 'year_ago' => ':count metus|:count metus|:count metų',
+ 'month_ago' => ':count mėnesį|:count mėnesius|:count mėnesių',
+ 'week_ago' => ':count savaitę|:count savaites|:count savaičių',
+ 'day_ago' => ':count dieną|:count dienas|:count dienų',
+ 'hour_ago' => ':count valandą|:count valandas|:count valandų',
+ 'minute_ago' => ':count minutę|:count minutes|:count minučių',
+ 'second_ago' => ':count sekundę|:count sekundes|:count sekundžių',
+
+ 'year_from_now' => ':count metų',
+ 'month_from_now' => ':count mėnesio|:count mėnesių|:count mėnesių',
+ 'week_from_now' => ':count savaitės|:count savaičių|:count savaičių',
+ 'day_from_now' => ':count dienos|:count dienų|:count dienų',
+ 'hour_from_now' => ':count valandos|:count valandų|:count valandų',
+ 'minute_from_now' => ':count minutės|:count minučių|:count minučių',
+ 'second_from_now' => ':count sekundės|:count sekundžių|:count sekundžių',
+
+ 'year_after' => ':count metų',
+ 'month_after' => ':count mėnesio|:count mėnesių|:count mėnesių',
+ 'week_after' => ':count savaitės|:count savaičių|:count savaičių',
+ 'day_after' => ':count dienos|:count dienų|:count dienų',
+ 'hour_after' => ':count valandos|:count valandų|:count valandų',
+ 'minute_after' => ':count minutės|:count minučių|:count minučių',
+ 'second_after' => ':count sekundės|:count sekundžių|:count sekundžių',
+
+ 'ago' => 'prieš :time',
+ 'from_now' => ':time nuo dabar',
+ 'after' => 'po :time',
+ 'before' => 'už :time',
+
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'diff_now' => 'ką tik',
+ 'diff_today' => 'Šiandien',
+ 'diff_yesterday' => 'vakar',
+ 'diff_yesterday_regexp' => 'Vakar',
+ 'diff_tomorrow' => 'rytoj',
+ 'diff_tomorrow_regexp' => 'Rytoj',
+ 'diff_before_yesterday' => 'užvakar',
+ 'diff_after_tomorrow' => 'poryt',
+
+ 'period_recurrences' => 'kartą|:count kartų',
+ 'period_interval' => 'kiekvieną :interval',
+ 'period_start_date' => 'nuo :date',
+ 'period_end_date' => 'iki :date',
+
+ 'months' => ['sausio', 'vasario', 'kovo', 'balandžio', 'gegužės', 'birželio', 'liepos', 'rugpjūčio', 'rugsėjo', 'spalio', 'lapkričio', 'gruodžio'],
+ 'months_standalone' => ['sausis', 'vasaris', 'kovas', 'balandis', 'gegužė', 'birželis', 'liepa', 'rugpjūtis', 'rugsėjis', 'spalis', 'lapkritis', 'gruodis'],
+ 'months_regexp' => '/(L{2,4}|D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?)/',
+ 'months_short' => ['sau', 'vas', 'kov', 'bal', 'geg', 'bir', 'lie', 'rgp', 'rgs', 'spa', 'lap', 'gru'],
+ 'weekdays' => ['sekmadienį', 'pirmadienį', 'antradienį', 'trečiadienį', 'ketvirtadienį', 'penktadienį', 'šeštadienį'],
+ 'weekdays_standalone' => ['sekmadienis', 'pirmadienis', 'antradienis', 'trečiadienis', 'ketvirtadienis', 'penktadienis', 'šeštadienis'],
+ 'weekdays_short' => ['sek', 'pir', 'ant', 'tre', 'ket', 'pen', 'šeš'],
+ 'weekdays_min' => ['se', 'pi', 'an', 'tr', 'ke', 'pe', 'še'],
+ 'list' => [', ', ' ir '],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'MMMM DD, YYYY',
+ 'LLL' => 'DD MMM HH:mm',
+ 'LLLL' => 'MMMM DD, YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Šiandien] LT',
+ 'nextDay' => '[Rytoj] LT',
+ 'nextWeek' => 'dddd LT',
+ 'lastDay' => '[Vakar] LT',
+ 'lastWeek' => '[Paskutinį] dddd LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ switch ($number) {
+ case 0:
+ return '0-is';
+ case 3:
+ return '3-ias';
+ default:
+ return "$number-as";
+ }
+ },
+ 'meridiem' => ['priešpiet', 'popiet'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lt_LT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lt_LT.php
new file mode 100644
index 0000000..c3087f4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lt_LT.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/lt.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lu.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lu.php
new file mode 100644
index 0000000..8dab541
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lu.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Dinda', 'Dilolo'],
+ 'weekdays' => ['Lumingu', 'Nkodya', 'Ndàayà', 'Ndangù', 'Njòwa', 'Ngòvya', 'Lubingu'],
+ 'weekdays_short' => ['Lum', 'Nko', 'Ndy', 'Ndg', 'Njw', 'Ngv', 'Lub'],
+ 'weekdays_min' => ['Lum', 'Nko', 'Ndy', 'Ndg', 'Njw', 'Ngv', 'Lub'],
+ 'months' => ['Ciongo', 'Lùishi', 'Lusòlo', 'Mùuyà', 'Lumùngùlù', 'Lufuimi', 'Kabàlàshìpù', 'Lùshìkà', 'Lutongolo', 'Lungùdi', 'Kaswèkèsè', 'Ciswà'],
+ 'months_short' => ['Cio', 'Lui', 'Lus', 'Muu', 'Lum', 'Luf', 'Kab', 'Lush', 'Lut', 'Lun', 'Kas', 'Cis'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/luo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/luo.php
new file mode 100644
index 0000000..201ca96
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/luo.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['OD', 'OT'],
+ 'weekdays' => ['Jumapil', 'Wuok Tich', 'Tich Ariyo', 'Tich Adek', 'Tich Ang’wen', 'Tich Abich', 'Ngeso'],
+ 'weekdays_short' => ['JMP', 'WUT', 'TAR', 'TAD', 'TAN', 'TAB', 'NGS'],
+ 'weekdays_min' => ['JMP', 'WUT', 'TAR', 'TAD', 'TAN', 'TAB', 'NGS'],
+ 'months' => ['Dwe mar Achiel', 'Dwe mar Ariyo', 'Dwe mar Adek', 'Dwe mar Ang’wen', 'Dwe mar Abich', 'Dwe mar Auchiel', 'Dwe mar Abiriyo', 'Dwe mar Aboro', 'Dwe mar Ochiko', 'Dwe mar Apar', 'Dwe mar gi achiel', 'Dwe mar Apar gi ariyo'],
+ 'months_short' => ['DAC', 'DAR', 'DAD', 'DAN', 'DAH', 'DAU', 'DAO', 'DAB', 'DOC', 'DAP', 'DGI', 'DAG'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => 'higni :count',
+ 'y' => 'higni :count',
+ 'a_year' => ':higni :count',
+
+ 'month' => 'dweche :count',
+ 'm' => 'dweche :count',
+ 'a_month' => 'dweche :count',
+
+ 'week' => 'jumbe :count',
+ 'w' => 'jumbe :count',
+ 'a_week' => 'jumbe :count',
+
+ 'day' => 'ndalo :count',
+ 'd' => 'ndalo :count',
+ 'a_day' => 'ndalo :count',
+
+ 'hour' => 'seche :count',
+ 'h' => 'seche :count',
+ 'a_hour' => 'seche :count',
+
+ 'minute' => 'dakika :count',
+ 'min' => 'dakika :count',
+ 'a_minute' => 'dakika :count',
+
+ 'second' => 'nus dakika :count',
+ 's' => 'nus dakika :count',
+ 'a_second' => 'nus dakika :count',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/luy.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/luy.php
new file mode 100644
index 0000000..5219125
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/luy.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'weekdays' => ['Jumapiri', 'Jumatatu', 'Jumanne', 'Jumatano', 'Murwa wa Kanne', 'Murwa wa Katano', 'Jumamosi'],
+ 'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
+ 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
+ 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+
+ // Too unreliable
+ /*
+ 'year' => ':count liliino', // less reliable
+ 'y' => ':count liliino', // less reliable
+ 'a_year' => ':count liliino', // less reliable
+
+ 'month' => ':count kumwesi', // less reliable
+ 'm' => ':count kumwesi', // less reliable
+ 'a_month' => ':count kumwesi', // less reliable
+
+ 'week' => ':count olutambi', // less reliable
+ 'w' => ':count olutambi', // less reliable
+ 'a_week' => ':count olutambi', // less reliable
+
+ 'day' => ':count luno', // less reliable
+ 'd' => ':count luno', // less reliable
+ 'a_day' => ':count luno', // less reliable
+
+ 'hour' => ':count ekengele', // less reliable
+ 'h' => ':count ekengele', // less reliable
+ 'a_hour' => ':count ekengele', // less reliable
+
+ 'minute' => ':count omundu', // less reliable
+ 'min' => ':count omundu', // less reliable
+ 'a_minute' => ':count omundu', // less reliable
+
+ 'second' => ':count liliino', // less reliable
+ 's' => ':count liliino', // less reliable
+ 'a_second' => ':count liliino', // less reliable
+ */
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lv.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lv.php
new file mode 100644
index 0000000..724b58d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lv.php
@@ -0,0 +1,173 @@
+<?php
+
+use Carbon\CarbonInterface;
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - pirminis
+ * - Tsutomu Kuroda
+ * - tjku
+ * - Andris Zāģeris
+ * - Max Melentiev
+ * - Edgars Beigarts
+ * - Juanito Fatas
+ * - Vitauts Stočka
+ * - Akira Matsuda
+ * - Christopher Dell
+ * - Enrique Vidal
+ * - Simone Carletti
+ * - Aaron Patterson
+ * - Kaspars Bankovskis
+ * - Nicolás Hock Isaza
+ * - Viesturs Kavacs (Kavacky)
+ * - zakse
+ * - Janis Eglitis (janiseglitis)
+ * - Guntars
+ * - Juris Sudmalis
+ */
+$daysOfWeek = ['svētdiena', 'pirmdiena', 'otrdiena', 'trešdiena', 'ceturtdiena', 'piektdiena', 'sestdiena'];
+$daysOfWeekLocativum = ['svētdien', 'pirmdien', 'otrdien', 'trešdien', 'ceturtdien', 'piektdien', 'sestdien'];
+
+$transformDiff = function ($input) {
+ return strtr($input, [
+ // Nominative => "pirms/pēc" Dative
+ 'gads' => 'gada',
+ 'gadi' => 'gadiem',
+ 'gadu' => 'gadiem',
+ 'mēnesis' => 'mēneša',
+ 'mēneši' => 'mēnešiem',
+ 'mēnešu' => 'mēnešiem',
+ 'nedēļa' => 'nedēļas',
+ 'nedēļas' => 'nedēļām',
+ 'nedēļu' => 'nedēļām',
+ 'diena' => 'dienas',
+ 'dienas' => 'dienām',
+ 'dienu' => 'dienām',
+ 'stunda' => 'stundas',
+ 'stundas' => 'stundām',
+ 'stundu' => 'stundām',
+ 'minūte' => 'minūtes',
+ 'minūtes' => 'minūtēm',
+ 'minūšu' => 'minūtēm',
+ 'sekunde' => 'sekundes',
+ 'sekundes' => 'sekundēm',
+ 'sekunžu' => 'sekundēm',
+ ]);
+};
+
+return [
+ 'ago' => function ($time) use ($transformDiff) {
+ return 'pirms '.$transformDiff($time);
+ },
+ 'from_now' => function ($time) use ($transformDiff) {
+ return 'pēc '.$transformDiff($time);
+ },
+
+ 'year' => '0 gadu|:count gads|:count gadi',
+ 'y' => ':count g.',
+ 'a_year' => '{1}gads|0 gadu|:count gads|:count gadi',
+ 'month' => '0 mēnešu|:count mēnesis|:count mēneši',
+ 'm' => ':count mēn.',
+ 'a_month' => '{1}mēnesis|0 mēnešu|:count mēnesis|:count mēneši',
+ 'week' => '0 nedēļu|:count nedēļa|:count nedēļas',
+ 'w' => ':count ned.',
+ 'a_week' => '{1}nedēļa|0 nedēļu|:count nedēļa|:count nedēļas',
+ 'day' => '0 dienu|:count diena|:count dienas',
+ 'd' => ':count d.',
+ 'a_day' => '{1}diena|0 dienu|:count diena|:count dienas',
+ 'hour' => '0 stundu|:count stunda|:count stundas',
+ 'h' => ':count st.',
+ 'a_hour' => '{1}stunda|0 stundu|:count stunda|:count stundas',
+ 'minute' => '0 minūšu|:count minūte|:count minūtes',
+ 'min' => ':count min.',
+ 'a_minute' => '{1}minūte|0 minūšu|:count minūte|:count minūtes',
+ 'second' => '0 sekunžu|:count sekunde|:count sekundes',
+ 's' => ':count sek.',
+ 'a_second' => '{1}sekunde|0 sekunžu|:count sekunde|:count sekundes',
+
+ 'after' => ':time vēlāk',
+ 'year_after' => '0 gadus|:count gadu|:count gadus',
+ 'a_year_after' => '{1}gadu|0 gadus|:count gadu|:count gadus',
+ 'month_after' => '0 mēnešus|:count mēnesi|:count mēnešus',
+ 'a_month_after' => '{1}mēnesi|0 mēnešus|:count mēnesi|:count mēnešus',
+ 'week_after' => '0 nedēļas|:count nedēļu|:count nedēļas',
+ 'a_week_after' => '{1}nedēļu|0 nedēļas|:count nedēļu|:count nedēļas',
+ 'day_after' => '0 dienas|:count dienu|:count dienas',
+ 'a_day_after' => '{1}dienu|0 dienas|:count dienu|:count dienas',
+ 'hour_after' => '0 stundas|:count stundu|:count stundas',
+ 'a_hour_after' => '{1}stundu|0 stundas|:count stundu|:count stundas',
+ 'minute_after' => '0 minūtes|:count minūti|:count minūtes',
+ 'a_minute_after' => '{1}minūti|0 minūtes|:count minūti|:count minūtes',
+ 'second_after' => '0 sekundes|:count sekundi|:count sekundes',
+ 'a_second_after' => '{1}sekundi|0 sekundes|:count sekundi|:count sekundes',
+
+ 'before' => ':time agrāk',
+ 'year_before' => '0 gadus|:count gadu|:count gadus',
+ 'a_year_before' => '{1}gadu|0 gadus|:count gadu|:count gadus',
+ 'month_before' => '0 mēnešus|:count mēnesi|:count mēnešus',
+ 'a_month_before' => '{1}mēnesi|0 mēnešus|:count mēnesi|:count mēnešus',
+ 'week_before' => '0 nedēļas|:count nedēļu|:count nedēļas',
+ 'a_week_before' => '{1}nedēļu|0 nedēļas|:count nedēļu|:count nedēļas',
+ 'day_before' => '0 dienas|:count dienu|:count dienas',
+ 'a_day_before' => '{1}dienu|0 dienas|:count dienu|:count dienas',
+ 'hour_before' => '0 stundas|:count stundu|:count stundas',
+ 'a_hour_before' => '{1}stundu|0 stundas|:count stundu|:count stundas',
+ 'minute_before' => '0 minūtes|:count minūti|:count minūtes',
+ 'a_minute_before' => '{1}minūti|0 minūtes|:count minūti|:count minūtes',
+ 'second_before' => '0 sekundes|:count sekundi|:count sekundes',
+ 'a_second_before' => '{1}sekundi|0 sekundes|:count sekundi|:count sekundes',
+
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' un '],
+
+ 'diff_now' => 'tagad',
+ 'diff_today' => 'šodien',
+ 'diff_yesterday' => 'vakar',
+ 'diff_before_yesterday' => 'aizvakar',
+ 'diff_tomorrow' => 'rīt',
+ 'diff_after_tomorrow' => 'parīt',
+
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY.',
+ 'LL' => 'YYYY. [gada] D. MMMM',
+ 'LLL' => 'DD.MM.YYYY., HH:mm',
+ 'LLLL' => 'YYYY. [gada] D. MMMM, HH:mm',
+ ],
+
+ 'calendar' => [
+ 'sameDay' => '[šodien] [plkst.] LT',
+ 'nextDay' => '[rīt] [plkst.] LT',
+ 'nextWeek' => function (CarbonInterface $current, CarbonInterface $other) use ($daysOfWeekLocativum) {
+ if ($current->week !== $other->week) {
+ return '[nākošo] ['.$daysOfWeekLocativum[$current->dayOfWeek].'] [plkst.] LT';
+ }
+
+ return '['.$daysOfWeekLocativum[$current->dayOfWeek].'] [plkst.] LT';
+ },
+ 'lastDay' => '[vakar] [plkst.] LT',
+ 'lastWeek' => function (CarbonInterface $current) use ($daysOfWeekLocativum) {
+ return '[pagājušo] ['.$daysOfWeekLocativum[$current->dayOfWeek].'] [plkst.] LT';
+ },
+ 'sameElse' => 'L',
+ ],
+
+ 'weekdays' => $daysOfWeek,
+ 'weekdays_short' => ['Sv.', 'P.', 'O.', 'T.', 'C.', 'Pk.', 'S.'],
+ 'weekdays_min' => ['Sv.', 'P.', 'O.', 'T.', 'C.', 'Pk.', 'S.'],
+ 'months' => ['janvārī', 'februārī', 'martā', 'aprīlī', 'maijā', 'jūnijā', 'jūlijā', 'augustā', 'septembrī', 'oktobrī', 'novembrī', 'decembrī'],
+ 'months_short' => ['Janv', 'Feb', 'Mar', 'Apr', 'Mai', 'Jūn', 'Jūl', 'Aug', 'Sept', 'Okt', 'Nov', 'Dec'],
+ 'meridiem' => ['priekšpusdiena', 'pēcpusdiena'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lv_LV.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lv_LV.php
new file mode 100644
index 0000000..46c0f43
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lv_LV.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/lv.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lzh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lzh.php
new file mode 100644
index 0000000..1180c6b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lzh.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/lzh_TW.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lzh_TW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lzh_TW.php
new file mode 100644
index 0000000..3b1493e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/lzh_TW.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'OY[年]MMMMOD[日]',
+ ],
+ 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ 'months_short' => [' 一 ', ' 二 ', ' 三 ', ' 四 ', ' 五 ', ' 六 ', ' 七 ', ' 八 ', ' 九 ', ' 十 ', '十一', '十二'],
+ 'weekdays' => ['週日', '週一', '週二', '週三', '週四', '週五', '週六'],
+ 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'day_of_first_week_of_year' => 1,
+ 'alt_numbers' => ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '廿', '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '卅', '卅一'],
+ 'meridiem' => ['朝', '暮'],
+
+ 'year' => ':count 夏', // less reliable
+ 'y' => ':count 夏', // less reliable
+ 'a_year' => ':count 夏', // less reliable
+
+ 'month' => ':count 月', // less reliable
+ 'm' => ':count 月', // less reliable
+ 'a_month' => ':count 月', // less reliable
+
+ 'hour' => ':count 氧', // less reliable
+ 'h' => ':count 氧', // less reliable
+ 'a_hour' => ':count 氧', // less reliable
+
+ 'minute' => ':count 點', // less reliable
+ 'min' => ':count 點', // less reliable
+ 'a_minute' => ':count 點', // less reliable
+
+ 'second' => ':count 楚', // less reliable
+ 's' => ':count 楚', // less reliable
+ 'a_second' => ':count 楚', // less reliable
+
+ 'week' => ':count 星期',
+ 'w' => ':count 星期',
+ 'a_week' => ':count 星期',
+
+ 'day' => ':count 日(曆法)',
+ 'd' => ':count 日(曆法)',
+ 'a_day' => ':count 日(曆法)',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mag.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mag.php
new file mode 100644
index 0000000..7532436
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mag.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/mag_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mag_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mag_IN.php
new file mode 100644
index 0000000..193f67a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mag_IN.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bhashaghar@googlegroups.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
+ 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
+ 'weekdays' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'],
+ 'weekdays_short' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'],
+ 'weekdays_min' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mai.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mai.php
new file mode 100644
index 0000000..792b973
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mai.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/mai_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mai_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mai_IN.php
new file mode 100644
index 0000000..03049d4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mai_IN.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Maithili Computing Research Center, Pune, India rajeshkajha@yahoo.com,akhilesh.k@samusng.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['बैसाख', 'जेठ', 'अषाढ़', 'सावोन', 'भादो', 'आसिन', 'कातिक', 'अगहन', 'पूस', 'माघ', 'फागुन', 'चैति'],
+ 'months_short' => ['बैसाख', 'जेठ', 'अषाढ़', 'सावोन', 'भादो', 'आसिन', 'कातिक', 'अगहन', 'पूस', 'माघ', 'फागुन', 'चैति'],
+ 'weekdays' => ['रविदिन', 'सोमदिन', 'मंगलदिन', 'बुधदिन', 'बृहस्पतीदिन', 'शुक्रदिन', 'शनीदिन'],
+ 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पती', 'शुक्र', 'शनी'],
+ 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पती', 'शुक्र', 'शनी'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
+
+ 'year' => ':count ऋतु', // less reliable
+ 'y' => ':count ऋतु', // less reliable
+ 'a_year' => ':count ऋतु', // less reliable
+
+ 'month' => ':count महिना',
+ 'm' => ':count महिना',
+ 'a_month' => ':count महिना',
+
+ 'week' => ':count श्रेणी:क्यालेन्डर', // less reliable
+ 'w' => ':count श्रेणी:क्यालेन्डर', // less reliable
+ 'a_week' => ':count श्रेणी:क्यालेन्डर', // less reliable
+
+ 'day' => ':count दिन',
+ 'd' => ':count दिन',
+ 'a_day' => ':count दिन',
+
+ 'hour' => ':count घण्टा',
+ 'h' => ':count घण्टा',
+ 'a_hour' => ':count घण्टा',
+
+ 'minute' => ':count समय', // less reliable
+ 'min' => ':count समय', // less reliable
+ 'a_minute' => ':count समय', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mas.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mas.php
new file mode 100644
index 0000000..723ae67
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mas.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Ɛnkakɛnyá', 'Ɛndámâ'],
+ 'weekdays' => ['Jumapílí', 'Jumatátu', 'Jumane', 'Jumatánɔ', 'Alaámisi', 'Jumáa', 'Jumamósi'],
+ 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'months' => ['Oladalʉ́', 'Arát', 'Ɔɛnɨ́ɔɨŋɔk', 'Olodoyíóríê inkókúâ', 'Oloilépūnyīē inkókúâ', 'Kújúɔrɔk', 'Mórusásin', 'Ɔlɔ́ɨ́bɔ́rárɛ', 'Kúshîn', 'Olgísan', 'Pʉshʉ́ka', 'Ntʉ́ŋʉ́s'],
+ 'months_short' => ['Dal', 'Ará', 'Ɔɛn', 'Doy', 'Lép', 'Rok', 'Sás', 'Bɔ́r', 'Kús', 'Gís', 'Shʉ́', 'Ntʉ́'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => ':count olameyu', // less reliable
+ 'y' => ':count olameyu', // less reliable
+ 'a_year' => ':count olameyu', // less reliable
+
+ 'week' => ':count engolongeare orwiki', // less reliable
+ 'w' => ':count engolongeare orwiki', // less reliable
+ 'a_week' => ':count engolongeare orwiki', // less reliable
+
+ 'hour' => ':count esahabu', // less reliable
+ 'h' => ':count esahabu', // less reliable
+ 'a_hour' => ':count esahabu', // less reliable
+
+ 'second' => ':count are', // less reliable
+ 's' => ':count are', // less reliable
+ 'a_second' => ':count are', // less reliable
+
+ 'month' => ':count olapa',
+ 'm' => ':count olapa',
+ 'a_month' => ':count olapa',
+
+ 'day' => ':count enkolongʼ',
+ 'd' => ':count enkolongʼ',
+ 'a_day' => ':count enkolongʼ',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mas_TZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mas_TZ.php
new file mode 100644
index 0000000..aa382b7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mas_TZ.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/mas.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mer.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mer.php
new file mode 100644
index 0000000..cb7ba8d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mer.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['RŨ', 'ŨG'],
+ 'weekdays' => ['Kiumia', 'Muramuko', 'Wairi', 'Wethatu', 'Wena', 'Wetano', 'Jumamosi'],
+ 'weekdays_short' => ['KIU', 'MRA', 'WAI', 'WET', 'WEN', 'WTN', 'JUM'],
+ 'weekdays_min' => ['KIU', 'MRA', 'WAI', 'WET', 'WEN', 'WTN', 'JUM'],
+ 'months' => ['Januarĩ', 'Feburuarĩ', 'Machi', 'Ĩpurũ', 'Mĩĩ', 'Njuni', 'Njuraĩ', 'Agasti', 'Septemba', 'Oktũba', 'Novemba', 'Dicemba'],
+ 'months_short' => ['JAN', 'FEB', 'MAC', 'ĨPU', 'MĨĨ', 'NJU', 'NJR', 'AGA', 'SPT', 'OKT', 'NOV', 'DEC'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => ':count murume', // less reliable
+ 'y' => ':count murume', // less reliable
+ 'a_year' => ':count murume', // less reliable
+
+ 'month' => ':count muchaara', // less reliable
+ 'm' => ':count muchaara', // less reliable
+ 'a_month' => ':count muchaara', // less reliable
+
+ 'minute' => ':count monto', // less reliable
+ 'min' => ':count monto', // less reliable
+ 'a_minute' => ':count monto', // less reliable
+
+ 'second' => ':count gikeno', // less reliable
+ 's' => ':count gikeno', // less reliable
+ 'a_second' => ':count gikeno', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mfe.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mfe.php
new file mode 100644
index 0000000..4d6e6b6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mfe.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/mfe_MU.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mfe_MU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mfe_MU.php
new file mode 100644
index 0000000..2d27b45
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mfe_MU.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['zanvie', 'fevriye', 'mars', 'avril', 'me', 'zin', 'zilye', 'out', 'septam', 'oktob', 'novam', 'desam'],
+ 'months_short' => ['zan', 'fev', 'mar', 'avr', 'me', 'zin', 'zil', 'out', 'sep', 'okt', 'nov', 'des'],
+ 'weekdays' => ['dimans', 'lindi', 'mardi', 'merkredi', 'zedi', 'vandredi', 'samdi'],
+ 'weekdays_short' => ['dim', 'lin', 'mar', 'mer', 'ze', 'van', 'sam'],
+ 'weekdays_min' => ['dim', 'lin', 'mar', 'mer', 'ze', 'van', 'sam'],
+
+ 'year' => ':count banané',
+ 'y' => ':count banané',
+ 'a_year' => ':count banané',
+
+ 'month' => ':count mwa',
+ 'm' => ':count mwa',
+ 'a_month' => ':count mwa',
+
+ 'week' => ':count sémenn',
+ 'w' => ':count sémenn',
+ 'a_week' => ':count sémenn',
+
+ 'day' => ':count zour',
+ 'd' => ':count zour',
+ 'a_day' => ':count zour',
+
+ 'hour' => ':count -er-tan',
+ 'h' => ':count -er-tan',
+ 'a_hour' => ':count -er-tan',
+
+ 'minute' => ':count minitt',
+ 'min' => ':count minitt',
+ 'a_minute' => ':count minitt',
+
+ 'second' => ':count déziém',
+ 's' => ':count déziém',
+ 'a_second' => ':count déziém',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mg.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mg.php
new file mode 100644
index 0000000..40bc2a8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mg.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/mg_MG.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mg_MG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mg_MG.php
new file mode 100644
index 0000000..6a14535
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mg_MG.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - The Debian Project modified by GNU//Linux Malagasy Rado Ramarotafika,Do-Risika RAFIEFERANTSIARONJY rado@linuxmg.org,dourix@free.fr
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['Janoary', 'Febroary', 'Martsa', 'Aprily', 'Mey', 'Jona', 'Jolay', 'Aogositra', 'Septambra', 'Oktobra', 'Novambra', 'Desambra'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mey', 'Jon', 'Jol', 'Aog', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'weekdays' => ['alahady', 'alatsinainy', 'talata', 'alarobia', 'alakamisy', 'zoma', 'sabotsy'],
+ 'weekdays_short' => ['lhd', 'lts', 'tlt', 'lrb', 'lkm', 'zom', 'sab'],
+ 'weekdays_min' => ['lhd', 'lts', 'tlt', 'lrb', 'lkm', 'zom', 'sab'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'minute' => ':count minitra', // less reliable
+ 'min' => ':count minitra', // less reliable
+ 'a_minute' => ':count minitra', // less reliable
+
+ 'year' => ':count taona',
+ 'y' => ':count taona',
+ 'a_year' => ':count taona',
+
+ 'month' => ':count volana',
+ 'm' => ':count volana',
+ 'a_month' => ':count volana',
+
+ 'week' => ':count herinandro',
+ 'w' => ':count herinandro',
+ 'a_week' => ':count herinandro',
+
+ 'day' => ':count andro',
+ 'd' => ':count andro',
+ 'a_day' => ':count andro',
+
+ 'hour' => ':count ora',
+ 'h' => ':count ora',
+ 'a_hour' => ':count ora',
+
+ 'second' => ':count segondra',
+ 's' => ':count segondra',
+ 'a_second' => ':count segondra',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mgh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mgh.php
new file mode 100644
index 0000000..65798a8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mgh.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['wichishu', 'mchochil’l'],
+ 'weekdays' => ['Sabato', 'Jumatatu', 'Jumanne', 'Jumatano', 'Arahamisi', 'Ijumaa', 'Jumamosi'],
+ 'weekdays_short' => ['Sab', 'Jtt', 'Jnn', 'Jtn', 'Ara', 'Iju', 'Jmo'],
+ 'weekdays_min' => ['Sab', 'Jtt', 'Jnn', 'Jtn', 'Ara', 'Iju', 'Jmo'],
+ 'months' => ['Mweri wo kwanza', 'Mweri wo unayeli', 'Mweri wo uneraru', 'Mweri wo unecheshe', 'Mweri wo unethanu', 'Mweri wo thanu na mocha', 'Mweri wo saba', 'Mweri wo nane', 'Mweri wo tisa', 'Mweri wo kumi', 'Mweri wo kumi na moja', 'Mweri wo kumi na yel’li'],
+ 'months_short' => ['Kwa', 'Una', 'Rar', 'Che', 'Tha', 'Moc', 'Sab', 'Nan', 'Tis', 'Kum', 'Moj', 'Yel'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mgo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mgo.php
new file mode 100644
index 0000000..a5a0754
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mgo.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'weekdays' => ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5', 'Aneg 6', 'Aneg 7'],
+ 'weekdays_short' => ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5', 'Aneg 6', 'Aneg 7'],
+ 'weekdays_min' => ['1', '2', '3', '4', '5', '6', '7'],
+ 'months' => ['iməg mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi', 'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ', 'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò', 'iməg krizmed'],
+ 'months_short' => ['mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi', 'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ', 'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò', 'iməg krizmed'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-dd',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'YYYY MMMM D HH:mm',
+ 'LLLL' => 'dddd, YYYY MMMM DD HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mhr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mhr.php
new file mode 100644
index 0000000..6bbc9f6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mhr.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/mhr_RU.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mhr_RU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mhr_RU.php
new file mode 100644
index 0000000..309ead9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mhr_RU.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - PeshSajSoft Ltd. Vyacheslav Kileev slavakileev@yandex.ru
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY.MM.DD',
+ ],
+ 'months' => ['Шорыкйол', 'Пургыж', 'Ӱярня', 'Вӱдшор', 'Ага', 'Пеледыш', 'Сӱрем', 'Сорла', 'Идым', 'Шыжа', 'Кылме', 'Теле'],
+ 'months_short' => ['Шрк', 'Пгж', 'Ӱрн', 'Вшр', 'Ага', 'Пдш', 'Срм', 'Срл', 'Идм', 'Шыж', 'Клм', 'Тел'],
+ 'weekdays' => ['Рушарня', 'Шочмо', 'Кушкыжмо', 'Вӱргече', 'Изарня', 'Кугарня', 'Шуматкече'],
+ 'weekdays_short' => ['Ршр', 'Шчм', 'Кжм', 'Вгч', 'Изр', 'Кгр', 'Шмт'],
+ 'weekdays_min' => ['Ршр', 'Шчм', 'Кжм', 'Вгч', 'Изр', 'Кгр', 'Шмт'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count идалык',
+ 'y' => ':count идалык',
+ 'a_year' => ':count идалык',
+
+ 'month' => ':count Тылзе',
+ 'm' => ':count Тылзе',
+ 'a_month' => ':count Тылзе',
+
+ 'week' => ':count арня',
+ 'w' => ':count арня',
+ 'a_week' => ':count арня',
+
+ 'day' => ':count кече',
+ 'd' => ':count кече',
+ 'a_day' => ':count кече',
+
+ 'hour' => ':count час',
+ 'h' => ':count час',
+ 'a_hour' => ':count час',
+
+ 'minute' => ':count минут',
+ 'min' => ':count минут',
+ 'a_minute' => ':count минут',
+
+ 'second' => ':count кокымшан',
+ 's' => ':count кокымшан',
+ 'a_second' => ':count кокымшан',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mi.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mi.php
new file mode 100644
index 0000000..b7f51ec
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mi.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - John Corrigan
+ * - François B
+ */
+return [
+ 'year' => ':count tau',
+ 'a_year' => '{1}he tau|:count tau',
+ 'month' => ':count marama',
+ 'a_month' => '{1}he marama|:count marama',
+ 'week' => ':count wiki',
+ 'a_week' => '{1}he wiki|:count wiki',
+ 'day' => ':count ra',
+ 'a_day' => '{1}he ra|:count ra',
+ 'hour' => ':count haora',
+ 'a_hour' => '{1}te haora|:count haora',
+ 'minute' => ':count meneti',
+ 'a_minute' => '{1}he meneti|:count meneti',
+ 'second' => ':count hēkona',
+ 'a_second' => '{1}te hēkona ruarua|:count hēkona',
+ 'ago' => ':time i mua',
+ 'from_now' => 'i roto i :time',
+ 'diff_yesterday' => 'inanahi',
+ 'diff_yesterday_regexp' => 'inanahi(?:\\s+i)?',
+ 'diff_today' => 'i teie',
+ 'diff_today_regexp' => 'i teie(?:\\s+mahana,)?(?:\\s+i)?',
+ 'diff_tomorrow' => 'apopo',
+ 'diff_tomorrow_regexp' => 'apopo(?:\\s+i)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY [i] HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY [i] HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[i teie mahana, i] LT',
+ 'nextDay' => '[apopo i] LT',
+ 'nextWeek' => 'dddd [i] LT',
+ 'lastDay' => '[inanahi i] LT',
+ 'lastWeek' => 'dddd [whakamutunga i] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numberº',
+ 'months' => ['Kohi-tāte', 'Hui-tanguru', 'Poutū-te-rangi', 'Paenga-whāwhā', 'Haratua', 'Pipiri', 'Hōngoingoi', 'Here-turi-kōkā', 'Mahuru', 'Whiringa-ā-nuku', 'Whiringa-ā-rangi', 'Hakihea'],
+ 'months_short' => ['Kohi', 'Hui', 'Pou', 'Pae', 'Hara', 'Pipi', 'Hōngoi', 'Here', 'Mahu', 'Whi-nu', 'Whi-ra', 'Haki'],
+ 'weekdays' => ['Rātapu', 'Mane', 'Tūrei', 'Wenerei', 'Tāite', 'Paraire', 'Hātarei'],
+ 'weekdays_short' => ['Ta', 'Ma', 'Tū', 'We', 'Tāi', 'Pa', 'Hā'],
+ 'weekdays_min' => ['Ta', 'Ma', 'Tū', 'We', 'Tāi', 'Pa', 'Hā'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' me te '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mi_NZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mi_NZ.php
new file mode 100644
index 0000000..123d229
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mi_NZ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/mi.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/miq.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/miq.php
new file mode 100644
index 0000000..51e5a98
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/miq.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/miq_NI.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/miq_NI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/miq_NI.php
new file mode 100644
index 0000000..b56783e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/miq_NI.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['siakwa kati', 'kuswa kati', 'kakamuk kati', 'lî wainhka kati', 'lih mairin kati', 'lî kati', 'pastara kati', 'sikla kati', 'wîs kati', 'waupasa kati', 'yahbra kati', 'trisu kati'],
+ 'months_short' => ['siakwa kati', 'kuswa kati', 'kakamuk kati', 'lî wainhka kati', 'lih mairin kati', 'lî kati', 'pastara kati', 'sikla kati', 'wîs kati', 'waupasa kati', 'yahbra kati', 'trisu kati'],
+ 'weekdays' => ['sandi', 'mundi', 'tiusdi', 'wensde', 'tausde', 'praidi', 'satadi'],
+ 'weekdays_short' => ['san', 'mun', 'tius', 'wens', 'taus', 'prai', 'sat'],
+ 'weekdays_min' => ['san', 'mun', 'tius', 'wens', 'taus', 'prai', 'sat'],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 7,
+ 'meridiem' => ['VM', 'NM'],
+
+ 'month' => ':count kati', // less reliable
+ 'm' => ':count kati', // less reliable
+ 'a_month' => ':count kati', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mjw.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mjw.php
new file mode 100644
index 0000000..617154c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mjw.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/mjw_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mjw_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mjw_IN.php
new file mode 100644
index 0000000..58ed0d1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mjw_IN.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Jor Teron bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['Arkoi', 'Thangthang', 'There', 'Jangmi', 'Aru', 'Vosik', 'Jakhong', 'Paipai', 'Chiti', 'Phere', 'Phaikuni', 'Matijong'],
+ 'months_short' => ['Ark', 'Thang', 'The', 'Jang', 'Aru', 'Vos', 'Jak', 'Pai', 'Chi', 'Phe', 'Phai', 'Mati'],
+ 'weekdays' => ['Bhomkuru', 'Urmi', 'Durmi', 'Thelang', 'Theman', 'Bhomta', 'Bhomti'],
+ 'weekdays_short' => ['Bhom', 'Ur', 'Dur', 'Tkel', 'Tkem', 'Bhta', 'Bhti'],
+ 'weekdays_min' => ['Bhom', 'Ur', 'Dur', 'Tkel', 'Tkem', 'Bhta', 'Bhti'],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mk.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mk.php
new file mode 100644
index 0000000..853bc96
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mk.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Sashko Todorov
+ * - Josh Soref
+ * - François B
+ * - Serhan Apaydın
+ * - Borislav Mickov
+ * - JD Isaacks
+ * - Tomi Atanasoski
+ */
+return [
+ 'year' => ':count година|:count години',
+ 'a_year' => 'година|:count години',
+ 'y' => ':count год.',
+ 'month' => ':count месец|:count месеци',
+ 'a_month' => 'месец|:count месеци',
+ 'm' => ':count месец|:count месеци',
+ 'week' => ':count седмица|:count седмици',
+ 'a_week' => 'седмица|:count седмици',
+ 'w' => ':count седмица|:count седмици',
+ 'day' => ':count ден|:count дена',
+ 'a_day' => 'ден|:count дена',
+ 'd' => ':count ден|:count дена',
+ 'hour' => ':count час|:count часа',
+ 'a_hour' => 'час|:count часа',
+ 'h' => ':count час|:count часа',
+ 'minute' => ':count минута|:count минути',
+ 'a_minute' => 'минута|:count минути',
+ 'min' => ':count мин.',
+ 'second' => ':count секунда|:count секунди',
+ 'a_second' => 'неколку секунди|:count секунди',
+ 's' => ':count сек.',
+ 'ago' => 'пред :time',
+ 'from_now' => 'после :time',
+ 'after' => 'по :time',
+ 'before' => 'пред :time',
+ 'diff_now' => 'сега',
+ 'diff_today' => 'Денес',
+ 'diff_today_regexp' => 'Денес(?:\\s+во)?',
+ 'diff_yesterday' => 'вчера',
+ 'diff_yesterday_regexp' => 'Вчера(?:\\s+во)?',
+ 'diff_tomorrow' => 'утре',
+ 'diff_tomorrow_regexp' => 'Утре(?:\\s+во)?',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'D.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY H:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Денес во] LT',
+ 'nextDay' => '[Утре во] LT',
+ 'nextWeek' => '[Во] dddd [во] LT',
+ 'lastDay' => '[Вчера во] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ case 3:
+ case 6:
+ return '[Изминатата] dddd [во] LT';
+ default:
+ return '[Изминатиот] dddd [во] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ $lastDigit = $number % 10;
+ $last2Digits = $number % 100;
+ if ($number === 0) {
+ return $number.'-ев';
+ }
+ if ($last2Digits === 0) {
+ return $number.'-ен';
+ }
+ if ($last2Digits > 10 && $last2Digits < 20) {
+ return $number.'-ти';
+ }
+ if ($lastDigit === 1) {
+ return $number.'-ви';
+ }
+ if ($lastDigit === 2) {
+ return $number.'-ри';
+ }
+ if ($lastDigit === 7 || $lastDigit === 8) {
+ return $number.'-ми';
+ }
+
+ return $number.'-ти';
+ },
+ 'months' => ['јануари', 'февруари', 'март', 'април', 'мај', 'јуни', 'јули', 'август', 'септември', 'октомври', 'ноември', 'декември'],
+ 'months_short' => ['јан', 'фев', 'мар', 'апр', 'мај', 'јун', 'јул', 'авг', 'сеп', 'окт', 'ное', 'дек'],
+ 'weekdays' => ['недела', 'понеделник', 'вторник', 'среда', 'четврток', 'петок', 'сабота'],
+ 'weekdays_short' => ['нед', 'пон', 'вто', 'сре', 'чет', 'пет', 'саб'],
+ 'weekdays_min' => ['нe', 'пo', 'вт', 'ср', 'че', 'пе', 'сa'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' и '],
+ 'meridiem' => ['АМ', 'ПМ'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mk_MK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mk_MK.php
new file mode 100644
index 0000000..06ff7d9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mk_MK.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/mk.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ml.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ml.php
new file mode 100644
index 0000000..1abd6c4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ml.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - JD Isaacks
+ */
+return [
+ 'year' => ':count വർഷം',
+ 'a_year' => 'ഒരു വർഷം|:count വർഷം',
+ 'month' => ':count മാസം',
+ 'a_month' => 'ഒരു മാസം|:count മാസം',
+ 'week' => ':count ആഴ്ച',
+ 'a_week' => 'ഒരാഴ്ച|:count ആഴ്ച',
+ 'day' => ':count ദിവസം',
+ 'a_day' => 'ഒരു ദിവസം|:count ദിവസം',
+ 'hour' => ':count മണിക്കൂർ',
+ 'a_hour' => 'ഒരു മണിക്കൂർ|:count മണിക്കൂർ',
+ 'minute' => ':count മിനിറ്റ്',
+ 'a_minute' => 'ഒരു മിനിറ്റ്|:count മിനിറ്റ്',
+ 'second' => ':count സെക്കൻഡ്',
+ 'a_second' => 'അൽപ നിമിഷങ്ങൾ|:count സെക്കൻഡ്',
+ 'ago' => ':time മുൻപ്',
+ 'from_now' => ':time കഴിഞ്ഞ്',
+ 'diff_now' => 'ഇപ്പോൾ',
+ 'diff_today' => 'ഇന്ന്',
+ 'diff_yesterday' => 'ഇന്നലെ',
+ 'diff_tomorrow' => 'നാളെ',
+ 'formats' => [
+ 'LT' => 'A h:mm -നു',
+ 'LTS' => 'A h:mm:ss -നു',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, A h:mm -നു',
+ 'LLLL' => 'dddd, D MMMM YYYY, A h:mm -നു',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[ഇന്ന്] LT',
+ 'nextDay' => '[നാളെ] LT',
+ 'nextWeek' => 'dddd, LT',
+ 'lastDay' => '[ഇന്നലെ] LT',
+ 'lastWeek' => '[കഴിഞ്ഞ] dddd, LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'രാത്രി';
+ }
+ if ($hour < 12) {
+ return 'രാവിലെ';
+ }
+ if ($hour < 17) {
+ return 'ഉച്ച കഴിഞ്ഞ്';
+ }
+ if ($hour < 20) {
+ return 'വൈകുന്നേരം';
+ }
+
+ return 'രാത്രി';
+ },
+ 'months' => ['ജനുവരി', 'ഫെബ്രുവരി', 'മാർച്ച്', 'ഏപ്രിൽ', 'മേയ്', 'ജൂൺ', 'ജൂലൈ', 'ഓഗസ്റ്റ്', 'സെപ്റ്റംബർ', 'ഒക്ടോബർ', 'നവംബർ', 'ഡിസംബർ'],
+ 'months_short' => ['ജനു.', 'ഫെബ്രു.', 'മാർ.', 'ഏപ്രി.', 'മേയ്', 'ജൂൺ', 'ജൂലൈ.', 'ഓഗ.', 'സെപ്റ്റ.', 'ഒക്ടോ.', 'നവം.', 'ഡിസം.'],
+ 'weekdays' => ['ഞായറാഴ്ച', 'തിങ്കളാഴ്ച', 'ചൊവ്വാഴ്ച', 'ബുധനാഴ്ച', 'വ്യാഴാഴ്ച', 'വെള്ളിയാഴ്ച', 'ശനിയാഴ്ച'],
+ 'weekdays_short' => ['ഞായർ', 'തിങ്കൾ', 'ചൊവ്വ', 'ബുധൻ', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
+ 'weekdays_min' => ['ഞാ', 'തി', 'ചൊ', 'ബു', 'വ്യാ', 'വെ', 'ശ'],
+ 'list' => ', ',
+ 'weekend' => [0, 0],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ml_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ml_IN.php
new file mode 100644
index 0000000..20878dc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ml_IN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ml.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mn.php
new file mode 100644
index 0000000..25f65b3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mn.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @translator Batmandakh Erdenebileg <batmandakh.e@icloud.com>
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - Tsutomu Kuroda
+ * - tjku
+ * - Max Melentiev
+ * - Zolzaya Erdenebaatar
+ * - Tom Hughes
+ * - Akira Matsuda
+ * - Christopher Dell
+ * - Michael Kessler
+ * - Enrique Vidal
+ * - Simone Carletti
+ * - Aaron Patterson
+ * - Nicolás Hock Isaza
+ * - Ochirkhuyag
+ * - Batmandakh
+ */
+return [
+ 'year' => ':count жил',
+ 'y' => ':count жил',
+ 'month' => ':count сар',
+ 'm' => ':count сар',
+ 'week' => ':count долоо хоног',
+ 'w' => ':count долоо хоног',
+ 'day' => ':count өдөр',
+ 'd' => ':count өдөр',
+ 'hour' => ':count цаг',
+ 'h' => ':countц',
+ 'minute' => ':count минут',
+ 'min' => ':countм',
+ 'second' => ':count секунд',
+ 's' => ':countс',
+
+ 'ago' => ':timeн өмнө',
+ 'year_ago' => ':count жилий',
+ 'month_ago' => ':count сары',
+ 'day_ago' => ':count хоногий',
+ 'hour_ago' => ':count цагий',
+ 'minute_ago' => ':count минуты',
+ 'second_ago' => ':count секунды',
+
+ 'from_now' => 'одоогоос :time',
+ 'year_from_now' => ':count жилийн дараа',
+ 'month_from_now' => ':count сарын дараа',
+ 'day_from_now' => ':count хоногийн дараа',
+ 'hour_from_now' => ':count цагийн дараа',
+ 'minute_from_now' => ':count минутын дараа',
+ 'second_from_now' => ':count секундын дараа',
+
+ // Does it required to make translation for before, after as follows? hmm, I think we've made it with ago and from now keywords already. Anyway, I've included it just in case of undesired action...
+ 'after' => ':timeн дараа',
+ 'year_after' => ':count жилий',
+ 'month_after' => ':count сары',
+ 'day_after' => ':count хоногий',
+ 'hour_after' => ':count цагий',
+ 'minute_after' => ':count минуты',
+ 'second_after' => ':count секунды',
+
+ 'before' => ':timeн өмнө',
+ 'year_before' => ':count жилий',
+ 'month_before' => ':count сары',
+ 'day_before' => ':count хоногий',
+ 'hour_before' => ':count цагий',
+ 'minute_before' => ':count минуты',
+ 'second_before' => ':count секунды',
+
+ 'list' => ', ',
+ 'diff_now' => 'одоо',
+ 'diff_yesterday' => 'өчигдөр',
+ 'diff_tomorrow' => 'маргааш',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'YYYY MMMM DD',
+ 'LLL' => 'YY-MM-DD, HH:mm',
+ 'LLLL' => 'YYYY MMMM DD, HH:mm',
+ ],
+ 'weekdays' => ['Ням', 'Даваа', 'Мягмар', 'Лхагва', 'Пүрэв', 'Баасан', 'Бямба'],
+ 'weekdays_short' => ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'],
+ 'weekdays_min' => ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'],
+ 'months' => ['1 сар', '2 сар', '3 сар', '4 сар', '5 сар', '6 сар', '7 сар', '8 сар', '9 сар', '10 сар', '11 сар', '12 сар'],
+ 'months_short' => ['1 сар', '2 сар', '3 сар', '4 сар', '5 сар', '6 сар', '7 сар', '8 сар', '9 сар', '10 сар', '11 сар', '12 сар'],
+ 'meridiem' => ['өглөө', 'орой'],
+ 'first_day_of_week' => 1,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mn_MN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mn_MN.php
new file mode 100644
index 0000000..b8fef24
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mn_MN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/mn.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mni.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mni.php
new file mode 100644
index 0000000..cafa2f8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mni.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/mni_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mni_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mni_IN.php
new file mode 100644
index 0000000..45d430e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mni_IN.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Red Hat Pune libc-alpha@sourceware.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['জানুৱারি', 'ফেব্রুৱারি', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগষ্ট', 'সেপ্তেম্বর', 'ওক্তোবর', 'নবেম্বর', 'ডিসেম্বর'],
+ 'months_short' => ['জান', 'ফেব', 'মার', 'এপ্রি', 'মে', 'জুন', 'জুল', 'আগ', 'সেপ', 'ওক্ত', 'নবে', 'ডিস'],
+ 'weekdays' => ['নোংমাইজিং', 'নিংথৌকাবা', 'লৈবাকপোকপা', 'য়ুমশকৈশা', 'শগোলশেন', 'ইরাই', 'থাংজ'],
+ 'weekdays_short' => ['নোং', 'নিং', 'লৈবাক', 'য়ুম', 'শগোল', 'ইরা', 'থাং'],
+ 'weekdays_min' => ['নোং', 'নিং', 'লৈবাক', 'য়ুম', 'শগোল', 'ইরা', 'থাং'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['এ.ম.', 'প.ম.'],
+
+ 'year' => ':count ইসিং', // less reliable
+ 'y' => ':count ইসিং', // less reliable
+ 'a_year' => ':count ইসিং', // less reliable
+
+ 'second' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable
+ 's' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable
+ 'a_second' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mo.php
new file mode 100644
index 0000000..dd7c8f0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mo.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ro.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mr.php
new file mode 100644
index 0000000..4aaeafd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mr.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Vikram-enyota
+ */
+return [
+ 'year' => ':count वर्ष',
+ 'y' => ':count वर्ष',
+ 'month' => ':count महिना|:count महिने',
+ 'm' => ':count महिना|:count महिने',
+ 'week' => ':count आठवडा|:count आठवडे',
+ 'w' => ':count आठवडा|:count आठवडे',
+ 'day' => ':count दिवस',
+ 'd' => ':count दिवस',
+ 'hour' => ':count तास',
+ 'h' => ':count तास',
+ 'minute' => ':count मिनिटे',
+ 'min' => ':count मिनिटे',
+ 'second' => ':count सेकंद',
+ 's' => ':count सेकंद',
+
+ 'ago' => ':timeपूर्वी',
+ 'from_now' => ':timeमध्ये',
+ 'before' => ':timeपूर्वी',
+ 'after' => ':timeनंतर',
+
+ 'diff_now' => 'आत्ता',
+ 'diff_today' => 'आज',
+ 'diff_yesterday' => 'काल',
+ 'diff_tomorrow' => 'उद्या',
+
+ 'formats' => [
+ 'LT' => 'A h:mm वाजता',
+ 'LTS' => 'A h:mm:ss वाजता',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, A h:mm वाजता',
+ 'LLLL' => 'dddd, D MMMM YYYY, A h:mm वाजता',
+ ],
+
+ 'calendar' => [
+ 'sameDay' => '[आज] LT',
+ 'nextDay' => '[उद्या] LT',
+ 'nextWeek' => 'dddd, LT',
+ 'lastDay' => '[काल] LT',
+ 'lastWeek' => '[मागील] dddd, LT',
+ 'sameElse' => 'L',
+ ],
+
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'रात्री';
+ }
+ if ($hour < 10) {
+ return 'सकाळी';
+ }
+ if ($hour < 17) {
+ return 'दुपारी';
+ }
+ if ($hour < 20) {
+ return 'सायंकाळी';
+ }
+
+ return 'रात्री';
+ },
+
+ 'months' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ऑगस्ट', 'सप्टेंबर', 'ऑक्टोबर', 'नोव्हेंबर', 'डिसेंबर'],
+ 'months_short' => ['जाने.', 'फेब्रु.', 'मार्च.', 'एप्रि.', 'मे.', 'जून.', 'जुलै.', 'ऑग.', 'सप्टें.', 'ऑक्टो.', 'नोव्हें.', 'डिसें.'],
+ 'weekdays' => ['रविवार', 'सोमवार', 'मंगळवार', 'बुधवार', 'गुरूवार', 'शुक्रवार', 'शनिवार'],
+ 'weekdays_short' => ['रवि', 'सोम', 'मंगळ', 'बुध', 'गुरू', 'शुक्र', 'शनि'],
+ 'weekdays_min' => ['र', 'सो', 'मं', 'बु', 'गु', 'शु', 'श'],
+ 'list' => [', ', ' आणि '],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'weekend' => [0, 0],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mr_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mr_IN.php
new file mode 100644
index 0000000..556cefa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mr_IN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/mr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms.php
new file mode 100644
index 0000000..ed7d48f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms.php
@@ -0,0 +1,98 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - Azri Jamil
+ * - JD Isaacks
+ * - Josh Soref
+ * - Azri Jamil
+ * - Hariadi Hinta
+ * - Ashraf Kamarudin
+ */
+return [
+ 'year' => ':count tahun',
+ 'a_year' => '{1}setahun|]1,Inf[:count tahun',
+ 'y' => ':count tahun',
+ 'month' => ':count bulan',
+ 'a_month' => '{1}sebulan|]1,Inf[:count bulan',
+ 'm' => ':count bulan',
+ 'week' => ':count minggu',
+ 'a_week' => '{1}seminggu|]1,Inf[:count minggu',
+ 'w' => ':count minggu',
+ 'day' => ':count hari',
+ 'a_day' => '{1}sehari|]1,Inf[:count hari',
+ 'd' => ':count hari',
+ 'hour' => ':count jam',
+ 'a_hour' => '{1}sejam|]1,Inf[:count jam',
+ 'h' => ':count jam',
+ 'minute' => ':count minit',
+ 'a_minute' => '{1}seminit|]1,Inf[:count minit',
+ 'min' => ':count minit',
+ 'second' => ':count saat',
+ 'a_second' => '{1}beberapa saat|]1,Inf[:count saat',
+ 'millisecond' => ':count milisaat',
+ 'a_millisecond' => '{1}semilisaat|]1,Inf[:count milliseconds',
+ 'microsecond' => ':count mikrodetik',
+ 'a_microsecond' => '{1}semikrodetik|]1,Inf[:count mikrodetik',
+ 's' => ':count saat',
+ 'ago' => ':time yang lepas',
+ 'from_now' => ':time dari sekarang',
+ 'after' => ':time kemudian',
+ 'before' => ':time lepas',
+ 'diff_now' => 'sekarang',
+ 'diff_today' => 'Hari',
+ 'diff_today_regexp' => 'Hari(?:\\s+ini)?(?:\\s+pukul)?',
+ 'diff_yesterday' => 'semalam',
+ 'diff_yesterday_regexp' => 'Semalam(?:\\s+pukul)?',
+ 'diff_tomorrow' => 'esok',
+ 'diff_tomorrow_regexp' => 'Esok(?:\\s+pukul)?',
+ 'diff_before_yesterday' => 'kelmarin',
+ 'diff_after_tomorrow' => 'lusa',
+ 'formats' => [
+ 'LT' => 'HH.mm',
+ 'LTS' => 'HH.mm.ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY [pukul] HH.mm',
+ 'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Hari ini pukul] LT',
+ 'nextDay' => '[Esok pukul] LT',
+ 'nextWeek' => 'dddd [pukul] LT',
+ 'lastDay' => '[Kelmarin pukul] LT',
+ 'lastWeek' => 'dddd [lepas pukul] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour) {
+ if ($hour < 12) {
+ return 'pagi';
+ }
+ if ($hour < 15) {
+ return 'tengah hari';
+ }
+ if ($hour < 19) {
+ return 'petang';
+ }
+
+ return 'malam';
+ },
+ 'months' => ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun', 'Julai', 'Ogos', 'September', 'Oktober', 'November', 'Disember'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ogs', 'Sep', 'Okt', 'Nov', 'Dis'],
+ 'weekdays' => ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat', 'Sabtu'],
+ 'weekdays_short' => ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'],
+ 'weekdays_min' => ['Ah', 'Is', 'Sl', 'Rb', 'Km', 'Jm', 'Sb'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' dan '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms_BN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms_BN.php
new file mode 100644
index 0000000..ea2b453
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms_BN.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ms.php', [
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'D/MM/yy',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY, h:mm a',
+ 'LLLL' => 'dd MMMM YYYY, h:mm a',
+ ],
+ 'meridiem' => ['a', 'p'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms_MY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms_MY.php
new file mode 100644
index 0000000..970d604
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms_MY.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - Azri Jamil
+ * - JD Isaacks
+ */
+return require __DIR__.'/ms.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms_SG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms_SG.php
new file mode 100644
index 0000000..097a168
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ms_SG.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ms.php', [
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'D/MM/yy',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY, h:mm a',
+ 'LLLL' => 'dddd, D MMMM YYYY, h:mm a',
+ ],
+ 'meridiem' => ['a', 'p'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mt.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mt.php
new file mode 100644
index 0000000..e8aadcc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mt.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Alessandro Maruccia
+ */
+return [
+ 'year' => 'sena|:count sni|:count sni|:count sni',
+ 'y' => 'sa sena|:count snin|:count snin|:count snin',
+ 'month' => 'xahar|:count xhur|:count xhur|:count xhur',
+ 'm' => ':count xahar|:count xhur|:count xhur|:count xhur',
+ 'week' => 'gimgħa|:count ġimgħat|:count ġimgħat|:count ġimgħat',
+ 'w' => 'ġimgħa|:count ġimgħat|:count ġimgħat|:count ġimgħat',
+ 'day' => 'ġurnata|:count ġranet|:count ġranet|:count ġranet',
+ 'd' => 'ġurnata|:count ġranet|:count ġranet|:count ġranet',
+ 'hour' => 'siegħa|:count siegħat|:count siegħat|:count siegħat',
+ 'h' => 'siegħa|:count sigħat|:count sigħat|:count sigħat',
+ 'minute' => 'minuta|:count minuti|:count minuti|:count minuti',
+ 'min' => 'min.|:count min.|:count min.|:count min.',
+ 'second' => 'ftit sekondi|:count sekondi|:count sekondi|:count sekondi',
+ 's' => 'sek.|:count sek.|:count sek.|:count sek.',
+ 'ago' => ':time ilu',
+ 'from_now' => 'f’ :time',
+ 'diff_now' => 'issa',
+ 'diff_today' => 'Illum',
+ 'diff_today_regexp' => 'Illum(?:\\s+fil-)?',
+ 'diff_yesterday' => 'lbieraħ',
+ 'diff_yesterday_regexp' => 'Il-bieraħ(?:\\s+fil-)?',
+ 'diff_tomorrow' => 'għada',
+ 'diff_tomorrow_regexp' => 'Għada(?:\\s+fil-)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Illum fil-]LT',
+ 'nextDay' => '[Għada fil-]LT',
+ 'nextWeek' => 'dddd [fil-]LT',
+ 'lastDay' => '[Il-bieraħ fil-]LT',
+ 'lastWeek' => 'dddd [li għadda] [fil-]LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numberº',
+ 'months' => ['Jannar', 'Frar', 'Marzu', 'April', 'Mejju', 'Ġunju', 'Lulju', 'Awwissu', 'Settembru', 'Ottubru', 'Novembru', 'Diċembru'],
+ 'months_short' => ['Jan', 'Fra', 'Mar', 'Apr', 'Mej', 'Ġun', 'Lul', 'Aww', 'Set', 'Ott', 'Nov', 'Diċ'],
+ 'weekdays' => ['Il-Ħadd', 'It-Tnejn', 'It-Tlieta', 'L-Erbgħa', 'Il-Ħamis', 'Il-Ġimgħa', 'Is-Sibt'],
+ 'weekdays_short' => ['Ħad', 'Tne', 'Tli', 'Erb', 'Ħam', 'Ġim', 'Sib'],
+ 'weekdays_min' => ['Ħa', 'Tn', 'Tl', 'Er', 'Ħa', 'Ġi', 'Si'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' u '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mt_MT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mt_MT.php
new file mode 100644
index 0000000..6ec2b33
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mt_MT.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/mt.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mua.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mua.php
new file mode 100644
index 0000000..8f1f9dc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mua.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['comme', 'lilli'],
+ 'weekdays' => ['Com’yakke', 'Comlaaɗii', 'Comzyiiɗii', 'Comkolle', 'Comkaldǝɓlii', 'Comgaisuu', 'Comzyeɓsuu'],
+ 'weekdays_short' => ['Cya', 'Cla', 'Czi', 'Cko', 'Cka', 'Cga', 'Cze'],
+ 'weekdays_min' => ['Cya', 'Cla', 'Czi', 'Cko', 'Cka', 'Cga', 'Cze'],
+ 'months' => ['Fĩi Loo', 'Cokcwaklaŋne', 'Cokcwaklii', 'Fĩi Marfoo', 'Madǝǝuutǝbijaŋ', 'Mamǝŋgwãafahbii', 'Mamǝŋgwãalii', 'Madǝmbii', 'Fĩi Dǝɓlii', 'Fĩi Mundaŋ', 'Fĩi Gwahlle', 'Fĩi Yuru'],
+ 'months_short' => ['FLO', 'CLA', 'CKI', 'FMF', 'MAD', 'MBI', 'MLI', 'MAM', 'FDE', 'FMU', 'FGW', 'FYU'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/my.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/my.php
new file mode 100644
index 0000000..bbdfba4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/my.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - JD Isaacks
+ * - Nay Lin Aung
+ */
+return [
+ 'year' => '{1}တစ်နှစ်|]1,Inf[:count နှစ်',
+ 'y' => ':count နှစ်',
+ 'month' => '{1}တစ်လ|]1,Inf[:count လ',
+ 'm' => ':count လ',
+ 'week' => ':count ပတ်',
+ 'w' => ':count ပတ်',
+ 'day' => '{1}တစ်ရက်|]1,Inf[:count ရက်',
+ 'd' => ':count ရက်',
+ 'hour' => '{1}တစ်နာရီ|]1,Inf[:count နာရီ',
+ 'h' => ':count နာရီ',
+ 'minute' => '{1}တစ်မိနစ်|]1,Inf[:count မိနစ်',
+ 'min' => ':count မိနစ်',
+ 'second' => '{1}စက္ကန်.အနည်းငယ်|]1,Inf[:count စက္ကန့်',
+ 's' => ':count စက္ကန့်',
+ 'ago' => 'လွန်ခဲ့သော :time က',
+ 'from_now' => 'လာမည့် :time မှာ',
+ 'after' => ':time ကြာပြီးနောက်',
+ 'before' => ':time မတိုင်ခင်',
+ 'diff_now' => 'အခုလေးတင်',
+ 'diff_today' => 'ယနေ.',
+ 'diff_yesterday' => 'မနေ့က',
+ 'diff_yesterday_regexp' => 'မနေ.က',
+ 'diff_tomorrow' => 'မနက်ဖြန်',
+ 'diff_before_yesterday' => 'တမြန်နေ့က',
+ 'diff_after_tomorrow' => 'တဘက်ခါ',
+ 'period_recurrences' => ':count ကြိမ်',
+ 'formats' => [
+ 'LT' => 'Oh:Om A',
+ 'LTS' => 'Oh:Om:Os A',
+ 'L' => 'OD/OM/OY',
+ 'LL' => 'OD MMMM OY',
+ 'LLL' => 'OD MMMM OY Oh:Om A',
+ 'LLLL' => 'dddd OD MMMM OY Oh:Om A',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[ယနေ.] LT [မှာ]',
+ 'nextDay' => '[မနက်ဖြန်] LT [မှာ]',
+ 'nextWeek' => 'dddd LT [မှာ]',
+ 'lastDay' => '[မနေ.က] LT [မှာ]',
+ 'lastWeek' => '[ပြီးခဲ့သော] dddd LT [မှာ]',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['ဇန်နဝါရီ', 'ဖေဖော်ဝါရီ', 'မတ်', 'ဧပြီ', 'မေ', 'ဇွန်', 'ဇူလိုင်', 'သြဂုတ်', 'စက်တင်ဘာ', 'အောက်တိုဘာ', 'နိုဝင်ဘာ', 'ဒီဇင်ဘာ'],
+ 'months_short' => ['ဇန်', 'ဖေ', 'မတ်', 'ပြီ', 'မေ', 'ဇွန်', 'လိုင်', 'သြ', 'စက်', 'အောက်', 'နို', 'ဒီ'],
+ 'weekdays' => ['တနင်္ဂနွေ', 'တနင်္လာ', 'အင်္ဂါ', 'ဗုဒ္ဓဟူး', 'ကြာသပတေး', 'သောကြာ', 'စနေ'],
+ 'weekdays_short' => ['နွေ', 'လာ', 'ဂါ', 'ဟူး', 'ကြာ', 'သော', 'နေ'],
+ 'weekdays_min' => ['နွေ', 'လာ', 'ဂါ', 'ဟူး', 'ကြာ', 'သော', 'နေ'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'alt_numbers' => ['၀၀', '၀၁', '၀၂', '၀၃', '၀၄', '၀၅', '၀၆', '၀၇', '၀၈', '၀၉', '၁၀', '၁၁', '၁၂', '၁၃', '၁၄', '၁၅', '၁၆', '၁၇', '၁၈', '၁၉', '၂၀', '၂၁', '၂၂', '၂၃', '၂၄', '၂၅', '၂၆', '၂၇', '၂၈', '၂၉', '၃၀', '၃၁', '၃၂', '၃၃', '၃၄', '၃၅', '၃၆', '၃၇', '၃၈', '၃၉', '၄၀', '၄၁', '၄၂', '၄၃', '၄၄', '၄၅', '၄၆', '၄၇', '၄၈', '၄၉', '၅၀', '၅၁', '၅၂', '၅၃', '၅၄', '၅၅', '၅၆', '၅၇', '၅၈', '၅၉', '၆၀', '၆၁', '၆၂', '၆၃', '၆၄', '၆၅', '၆၆', '၆၇', '၆၈', '၆၉', '၇၀', '၇၁', '၇၂', '၇၃', '၇၄', '၇၅', '၇၆', '၇၇', '၇၈', '၇၉', '၈၀', '၈၁', '၈၂', '၈၃', '၈၄', '၈၅', '၈၆', '၈၇', '၈၈', '၈၉', '၉၀', '၉၁', '၉၂', '၉၃', '၉၄', '၉၅', '၉၆', '၉၇', '၉၈', '၉၉'],
+ 'meridiem' => ['နံနက်', 'ညနေ'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/my_MM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/my_MM.php
new file mode 100644
index 0000000..1f27cca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/my_MM.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/my.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mzn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mzn.php
new file mode 100644
index 0000000..6ad3604
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/mzn.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fa.php', [
+ 'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
+ 'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
+ 'first_day_of_week' => 6,
+ 'weekend' => [5, 5],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-dd',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'YYYY MMMM D HH:mm',
+ 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nan.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nan.php
new file mode 100644
index 0000000..0affece
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nan.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/nan_TW.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nan_TW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nan_TW.php
new file mode 100644
index 0000000..5c50aa4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nan_TW.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY年MM月DD日',
+ ],
+ 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ 'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'],
+ 'weekdays' => ['禮拜日', '禮拜一', '禮拜二', '禮拜三', '禮拜四', '禮拜五', '禮拜六'],
+ 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['頂晡', '下晡'],
+
+ 'year' => ':count 年',
+ 'y' => ':count 年',
+ 'a_year' => ':count 年',
+
+ 'month' => ':count goe̍h',
+ 'm' => ':count goe̍h',
+ 'a_month' => ':count goe̍h',
+
+ 'week' => ':count lé-pài',
+ 'w' => ':count lé-pài',
+ 'a_week' => ':count lé-pài',
+
+ 'day' => ':count 日',
+ 'd' => ':count 日',
+ 'a_day' => ':count 日',
+
+ 'hour' => ':count tiám-cheng',
+ 'h' => ':count tiám-cheng',
+ 'a_hour' => ':count tiám-cheng',
+
+ 'minute' => ':count Hun-cheng',
+ 'min' => ':count Hun-cheng',
+ 'a_minute' => ':count Hun-cheng',
+
+ 'second' => ':count Bió',
+ 's' => ':count Bió',
+ 'a_second' => ':count Bió',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nan_TW@latin.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nan_TW@latin.php
new file mode 100644
index 0000000..99ca2a4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nan_TW@latin.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Arne Goetje arne@canonical.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY-MM-DD',
+ ],
+ 'months' => ['1goe̍h', '2goe̍h', '3goe̍h', '4goe̍h', '5goe̍h', '6goe̍h', '7goe̍h', '8goe̍h', '9goe̍h', '10goe̍h', '11goe̍h', '12goe̍h'],
+ 'months_short' => ['1g', '2g', '3g', '4g', '5g', '6g', '7g', '8g', '9g', '10g', '11g', '12g'],
+ 'weekdays' => ['lé-pài-ji̍t', 'pài-it', 'pài-jī', 'pài-saⁿ', 'pài-sì', 'pài-gō͘', 'pài-la̍k'],
+ 'weekdays_short' => ['lp', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6'],
+ 'weekdays_min' => ['lp', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['téng-po͘', 'ē-po͘'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/naq.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/naq.php
new file mode 100644
index 0000000..614ced4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/naq.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['ǁgoagas', 'ǃuias'],
+ 'weekdays' => ['Sontaxtsees', 'Mantaxtsees', 'Denstaxtsees', 'Wunstaxtsees', 'Dondertaxtsees', 'Fraitaxtsees', 'Satertaxtsees'],
+ 'weekdays_short' => ['Son', 'Ma', 'De', 'Wu', 'Do', 'Fr', 'Sat'],
+ 'weekdays_min' => ['Son', 'Ma', 'De', 'Wu', 'Do', 'Fr', 'Sat'],
+ 'months' => ['ǃKhanni', 'ǃKhanǀgôab', 'ǀKhuuǁkhâb', 'ǃHôaǂkhaib', 'ǃKhaitsâb', 'Gamaǀaeb', 'ǂKhoesaob', 'Aoǁkhuumûǁkhâb', 'Taraǀkhuumûǁkhâb', 'ǂNûǁnâiseb', 'ǀHooǂgaeb', 'Hôasoreǁkhâb'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd, D MMMM YYYY h:mm a',
+ ],
+
+ 'year' => ':count kurigu',
+ 'y' => ':count kurigu',
+ 'a_year' => ':count kurigu',
+
+ 'month' => ':count ǁaub', // less reliable
+ 'm' => ':count ǁaub', // less reliable
+ 'a_month' => ':count ǁaub', // less reliable
+
+ 'week' => ':count hû', // less reliable
+ 'w' => ':count hû', // less reliable
+ 'a_week' => ':count hû', // less reliable
+
+ 'day' => ':count ǀhobas', // less reliable
+ 'd' => ':count ǀhobas', // less reliable
+ 'a_day' => ':count ǀhobas', // less reliable
+
+ 'hour' => ':count ǂgaes', // less reliable
+ 'h' => ':count ǂgaes', // less reliable
+ 'a_hour' => ':count ǂgaes', // less reliable
+
+ 'minute' => ':count minutga', // less reliable
+ 'min' => ':count minutga', // less reliable
+ 'a_minute' => ':count minutga', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nb.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nb.php
new file mode 100644
index 0000000..371ee84
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nb.php
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Alexander Tømmerås
+ * - Sigurd Gartmann
+ * - JD Isaacks
+ */
+return [
+ 'year' => ':count år|:count år',
+ 'a_year' => 'ett år|:count år',
+ 'y' => ':count år|:count år',
+ 'month' => ':count måned|:count måneder',
+ 'a_month' => 'en måned|:count måneder',
+ 'm' => ':count md.',
+ 'week' => ':count uke|:count uker',
+ 'a_week' => 'en uke|:count uker',
+ 'w' => ':count u.',
+ 'day' => ':count dag|:count dager',
+ 'a_day' => 'en dag|:count dager',
+ 'd' => ':count d.',
+ 'hour' => ':count time|:count timer',
+ 'a_hour' => 'en time|:count timer',
+ 'h' => ':count t',
+ 'minute' => ':count minutt|:count minutter',
+ 'a_minute' => 'ett minutt|:count minutter',
+ 'min' => ':count min',
+ 'second' => ':count sekund|:count sekunder',
+ 'a_second' => 'noen sekunder|:count sekunder',
+ 's' => ':count sek',
+ 'ago' => ':time siden',
+ 'from_now' => 'om :time',
+ 'after' => ':time etter',
+ 'before' => ':time før',
+ 'diff_now' => 'akkurat nå',
+ 'diff_today' => 'i dag',
+ 'diff_today_regexp' => 'i dag(?:\\s+kl.)?',
+ 'diff_yesterday' => 'i går',
+ 'diff_yesterday_regexp' => 'i går(?:\\s+kl.)?',
+ 'diff_tomorrow' => 'i morgen',
+ 'diff_tomorrow_regexp' => 'i morgen(?:\\s+kl.)?',
+ 'diff_before_yesterday' => 'i forgårs',
+ 'diff_after_tomorrow' => 'i overmorgen',
+ 'period_recurrences' => 'en gang|:count ganger',
+ 'period_interval' => 'hver :interval',
+ 'period_start_date' => 'fra :date',
+ 'period_end_date' => 'til :date',
+ 'months' => ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
+ 'weekdays' => ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'],
+ 'weekdays_short' => ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],
+ 'weekdays_min' => ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'],
+ 'ordinal' => ':number.',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY [kl.] HH:mm',
+ 'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[i dag kl.] LT',
+ 'nextDay' => '[i morgen kl.] LT',
+ 'nextWeek' => 'dddd [kl.] LT',
+ 'lastDay' => '[i går kl.] LT',
+ 'lastWeek' => '[forrige] dddd [kl.] LT',
+ 'sameElse' => 'L',
+ ],
+ 'list' => [', ', ' og '],
+ 'meridiem' => ['a.m.', 'p.m.'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nb_NO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nb_NO.php
new file mode 100644
index 0000000..bd643a8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nb_NO.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/nb.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nb_SJ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nb_SJ.php
new file mode 100644
index 0000000..93cbaef
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nb_SJ.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/nb.php', [
+ 'formats' => [
+ 'LL' => 'D. MMM YYYY',
+ 'LLL' => 'D. MMMM YYYY, HH:mm',
+ 'LLLL' => 'dddd D. MMMM YYYY, HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nd.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nd.php
new file mode 100644
index 0000000..d6fdaad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nd.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'weekdays' => ['Sonto', 'Mvulo', 'Sibili', 'Sithathu', 'Sine', 'Sihlanu', 'Mgqibelo'],
+ 'weekdays_short' => ['Son', 'Mvu', 'Sib', 'Sit', 'Sin', 'Sih', 'Mgq'],
+ 'weekdays_min' => ['Son', 'Mvu', 'Sib', 'Sit', 'Sin', 'Sih', 'Mgq'],
+ 'months' => ['Zibandlela', 'Nhlolanja', 'Mbimbitho', 'Mabasa', 'Nkwenkwezi', 'Nhlangula', 'Ntulikazi', 'Ncwabakazi', 'Mpandula', 'Mfumfu', 'Lwezi', 'Mpalakazi'],
+ 'months_short' => ['Zib', 'Nhlo', 'Mbi', 'Mab', 'Nkw', 'Nhla', 'Ntu', 'Ncw', 'Mpan', 'Mfu', 'Lwe', 'Mpal'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => 'okweminyaka engu-:count', // less reliable
+ 'y' => 'okweminyaka engu-:count', // less reliable
+ 'a_year' => 'okweminyaka engu-:count', // less reliable
+
+ 'month' => 'inyanga ezingu-:count',
+ 'm' => 'inyanga ezingu-:count',
+ 'a_month' => 'inyanga ezingu-:count',
+
+ 'week' => 'amaviki angu-:count',
+ 'w' => 'amaviki angu-:count',
+ 'a_week' => 'amaviki angu-:count',
+
+ 'day' => 'kwamalanga angu-:count',
+ 'd' => 'kwamalanga angu-:count',
+ 'a_day' => 'kwamalanga angu-:count',
+
+ 'hour' => 'amahola angu-:count',
+ 'h' => 'amahola angu-:count',
+ 'a_hour' => 'amahola angu-:count',
+
+ 'minute' => 'imizuzu engu-:count',
+ 'min' => 'imizuzu engu-:count',
+ 'a_minute' => 'imizuzu engu-:count',
+
+ 'second' => 'imizuzwana engu-:count',
+ 's' => 'imizuzwana engu-:count',
+ 'a_second' => 'imizuzwana engu-:count',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nds.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nds.php
new file mode 100644
index 0000000..c0b3775
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nds.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/nds_DE.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nds_DE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nds_DE.php
new file mode 100644
index 0000000..eb6e77e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nds_DE.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandrakesoft.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['Jannuaar', 'Feberwaar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
+ 'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
+ 'weekdays' => ['Sünndag', 'Maandag', 'Dingsdag', 'Middeweek', 'Dunnersdag', 'Freedag', 'Sünnavend'],
+ 'weekdays_short' => ['Sdag', 'Maan', 'Ding', 'Migg', 'Dunn', 'Free', 'Svd.'],
+ 'weekdays_min' => ['Sdag', 'Maan', 'Ding', 'Migg', 'Dunn', 'Free', 'Svd.'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'year' => ':count Johr',
+ 'y' => ':count Johr',
+ 'a_year' => ':count Johr',
+
+ 'month' => ':count Maand',
+ 'm' => ':count Maand',
+ 'a_month' => ':count Maand',
+
+ 'week' => ':count Week',
+ 'w' => ':count Week',
+ 'a_week' => ':count Week',
+
+ 'day' => ':count Dag',
+ 'd' => ':count Dag',
+ 'a_day' => ':count Dag',
+
+ 'hour' => ':count Stünn',
+ 'h' => ':count Stünn',
+ 'a_hour' => ':count Stünn',
+
+ 'minute' => ':count Minuut',
+ 'min' => ':count Minuut',
+ 'a_minute' => ':count Minuut',
+
+ 'second' => ':count sekunn',
+ 's' => ':count sekunn',
+ 'a_second' => ':count sekunn',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nds_NL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nds_NL.php
new file mode 100644
index 0000000..de2c57b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nds_NL.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandrakesoft.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['Jaunuwoa', 'Februwoa', 'Moaz', 'Aprell', 'Mai', 'Juni', 'Juli', 'August', 'Septamba', 'Oktoba', 'Nowamba', 'Dezamba'],
+ 'months_short' => ['Jan', 'Feb', 'Moz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Now', 'Dez'],
+ 'weekdays' => ['Sinndag', 'Mondag', 'Dingsdag', 'Meddwäakj', 'Donnadag', 'Friedag', 'Sinnowend'],
+ 'weekdays_short' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
+ 'weekdays_min' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ne.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ne.php
new file mode 100644
index 0000000..d4caf0e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ne.php
@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - nootanghimire
+ * - Josh Soref
+ * - Nj Subedi
+ * - JD Isaacks
+ */
+return [
+ 'year' => 'एक बर्ष|:count बर्ष',
+ 'y' => ':count वर्ष',
+ 'month' => 'एक महिना|:count महिना',
+ 'm' => ':count महिना',
+ 'week' => ':count हप्ता',
+ 'w' => ':count हप्ता',
+ 'day' => 'एक दिन|:count दिन',
+ 'd' => ':count दिन',
+ 'hour' => 'एक घण्टा|:count घण्टा',
+ 'h' => ':count घण्टा',
+ 'minute' => 'एक मिनेट|:count मिनेट',
+ 'min' => ':count मिनेट',
+ 'second' => 'केही क्षण|:count सेकेण्ड',
+ 's' => ':count सेकेण्ड',
+ 'ago' => ':time अगाडि',
+ 'from_now' => ':timeमा',
+ 'after' => ':time पछि',
+ 'before' => ':time अघि',
+ 'diff_now' => 'अहिले',
+ 'diff_today' => 'आज',
+ 'diff_yesterday' => 'हिजो',
+ 'diff_tomorrow' => 'भोलि',
+ 'formats' => [
+ 'LT' => 'Aको h:mm बजे',
+ 'LTS' => 'Aको h:mm:ss बजे',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, Aको h:mm बजे',
+ 'LLLL' => 'dddd, D MMMM YYYY, Aको h:mm बजे',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[आज] LT',
+ 'nextDay' => '[भोलि] LT',
+ 'nextWeek' => '[आउँदो] dddd[,] LT',
+ 'lastDay' => '[हिजो] LT',
+ 'lastWeek' => '[गएको] dddd[,] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour) {
+ if ($hour < 3) {
+ return 'राति';
+ }
+ if ($hour < 12) {
+ return 'बिहान';
+ }
+ if ($hour < 16) {
+ return 'दिउँसो';
+ }
+ if ($hour < 20) {
+ return 'साँझ';
+ }
+
+ return 'राति';
+ },
+ 'months' => ['जनवरी', 'फेब्रुवरी', 'मार्च', 'अप्रिल', 'मई', 'जुन', 'जुलाई', 'अगष्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'],
+ 'months_short' => ['जन.', 'फेब्रु.', 'मार्च', 'अप्रि.', 'मई', 'जुन', 'जुलाई.', 'अग.', 'सेप्ट.', 'अक्टो.', 'नोभे.', 'डिसे.'],
+ 'weekdays' => ['आइतबार', 'सोमबार', 'मङ्गलबार', 'बुधबार', 'बिहिबार', 'शुक्रबार', 'शनिबार'],
+ 'weekdays_short' => ['आइत.', 'सोम.', 'मङ्गल.', 'बुध.', 'बिहि.', 'शुक्र.', 'शनि.'],
+ 'weekdays_min' => ['आ.', 'सो.', 'मं.', 'बु.', 'बि.', 'शु.', 'श.'],
+ 'list' => [', ', ' र '],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ne_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ne_IN.php
new file mode 100644
index 0000000..2583bcf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ne_IN.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ne.php', [
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'yy/M/d',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'YYYY MMMM D, h:mm a',
+ 'LLLL' => 'YYYY MMMM D, dddd, h:mm a',
+ ],
+ 'months' => ['जनवरी', 'फेब्रुअरी', 'मार्च', 'अप्रिल', 'मे', 'जुन', 'जुलाई', 'अगस्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'],
+ 'months_short' => ['जनवरी', 'फेब्रुअरी', 'मार्च', 'अप्रिल', 'मे', 'जुन', 'जुलाई', 'अगस्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'],
+ 'weekend' => [0, 0],
+ 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ne_NP.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ne_NP.php
new file mode 100644
index 0000000..38caa1e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ne_NP.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ne.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nhn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nhn.php
new file mode 100644
index 0000000..5a85831
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nhn.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/nhn_MX.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nhn_MX.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nhn_MX.php
new file mode 100644
index 0000000..9db88a1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nhn_MX.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP libc-alpha@sourceware.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
+ 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
+ 'weekdays' => ['teoilhuitl', 'ceilhuitl', 'omeilhuitl', 'yeilhuitl', 'nahuilhuitl', 'macuililhuitl', 'chicuaceilhuitl'],
+ 'weekdays_short' => ['teo', 'cei', 'ome', 'yei', 'nau', 'mac', 'chi'],
+ 'weekdays_min' => ['teo', 'cei', 'ome', 'yei', 'nau', 'mac', 'chi'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'month' => ':count metztli', // less reliable
+ 'm' => ':count metztli', // less reliable
+ 'a_month' => ':count metztli', // less reliable
+
+ 'week' => ':count tonalli', // less reliable
+ 'w' => ':count tonalli', // less reliable
+ 'a_week' => ':count tonalli', // less reliable
+
+ 'day' => ':count tonatih', // less reliable
+ 'd' => ':count tonatih', // less reliable
+ 'a_day' => ':count tonatih', // less reliable
+
+ 'minute' => ':count toltecayotl', // less reliable
+ 'min' => ':count toltecayotl', // less reliable
+ 'a_minute' => ':count toltecayotl', // less reliable
+
+ 'second' => ':count ome', // less reliable
+ 's' => ':count ome', // less reliable
+ 'a_second' => ':count ome', // less reliable
+
+ 'year' => ':count xihuitl',
+ 'y' => ':count xihuitl',
+ 'a_year' => ':count xihuitl',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/niu.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/niu.php
new file mode 100644
index 0000000..bd9be8a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/niu.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/niu_NU.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/niu_NU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/niu_NU.php
new file mode 100644
index 0000000..6e7a697
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/niu_NU.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RockET Systems Emani Fakaotimanava-Lui emani@niue.nu
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['Ianuali', 'Fepuali', 'Masi', 'Apelila', 'Me', 'Iuni', 'Iulai', 'Aokuso', 'Sepetema', 'Oketopa', 'Novema', 'Tesemo'],
+ 'months_short' => ['Ian', 'Fep', 'Mas', 'Ape', 'Me', 'Iun', 'Iul', 'Aok', 'Sep', 'Oke', 'Nov', 'Tes'],
+ 'weekdays' => ['Aho Tapu', 'Aho Gofua', 'Aho Ua', 'Aho Lotu', 'Aho Tuloto', 'Aho Falaile', 'Aho Faiumu'],
+ 'weekdays_short' => ['Tapu', 'Gofua', 'Ua', 'Lotu', 'Tuloto', 'Falaile', 'Faiumu'],
+ 'weekdays_min' => ['Tapu', 'Gofua', 'Ua', 'Lotu', 'Tuloto', 'Falaile', 'Faiumu'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count tau',
+ 'y' => ':count tau',
+ 'a_year' => ':count tau',
+
+ 'month' => ':count mahina',
+ 'm' => ':count mahina',
+ 'a_month' => ':count mahina',
+
+ 'week' => ':count faahi tapu',
+ 'w' => ':count faahi tapu',
+ 'a_week' => ':count faahi tapu',
+
+ 'day' => ':count aho',
+ 'd' => ':count aho',
+ 'a_day' => ':count aho',
+
+ 'hour' => ':count e tulā',
+ 'h' => ':count e tulā',
+ 'a_hour' => ':count e tulā',
+
+ 'minute' => ':count minuti',
+ 'min' => ':count minuti',
+ 'a_minute' => ':count minuti',
+
+ 'second' => ':count sekone',
+ 's' => ':count sekone',
+ 'a_second' => ':count sekone',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl.php
new file mode 100644
index 0000000..fc8b5d9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Roy
+ * - Stephan
+ * - François B
+ * - Tim Fish
+ * - Kevin Huang
+ * - Jacob Middag
+ * - JD Isaacks
+ * - Roy
+ * - Stephan
+ * - François B
+ * - Tim Fish
+ * - Jacob Middag
+ * - JD Isaacks
+ * - Propaganistas
+ * - MegaXLR
+ * - adriaanzon
+ * - MonkeyPhysics
+ * - JeroenG
+ * - RikSomers
+ * - proclame
+ * - Rik de Groot (hwdegroot)
+ */
+return [
+ 'year' => ':count jaar|:count jaar',
+ 'a_year' => 'een jaar|:count jaar',
+ 'y' => ':countj',
+ 'month' => ':count maand|:count maanden',
+ 'a_month' => 'een maand|:count maanden',
+ 'm' => ':countmnd',
+ 'week' => ':count week|:count weken',
+ 'a_week' => 'een week|:count weken',
+ 'w' => ':countw',
+ 'day' => ':count dag|:count dagen',
+ 'a_day' => 'een dag|:count dagen',
+ 'd' => ':countd',
+ 'hour' => ':count uur|:count uur',
+ 'a_hour' => 'een uur|:count uur',
+ 'h' => ':countu',
+ 'minute' => ':count minuut|:count minuten',
+ 'a_minute' => 'een minuut|:count minuten',
+ 'min' => ':countmin',
+ 'second' => ':count seconde|:count seconden',
+ 'a_second' => 'een paar seconden|:count seconden',
+ 's' => ':counts',
+ 'ago' => ':time geleden',
+ 'from_now' => 'over :time',
+ 'after' => ':time later',
+ 'before' => ':time eerder',
+ 'diff_now' => 'nu',
+ 'diff_today' => 'vandaag',
+ 'diff_today_regexp' => 'vandaag(?:\\s+om)?',
+ 'diff_yesterday' => 'gisteren',
+ 'diff_yesterday_regexp' => 'gisteren(?:\\s+om)?',
+ 'diff_tomorrow' => 'morgen',
+ 'diff_tomorrow_regexp' => 'morgen(?:\\s+om)?',
+ 'diff_after_tomorrow' => 'overmorgen',
+ 'diff_before_yesterday' => 'eergisteren',
+ 'period_recurrences' => ':count keer',
+ 'period_interval' => function (string $interval = '') {
+ /** @var string $output */
+ $output = preg_replace('/^(een|één|1)\s+/', '', $interval);
+
+ if (preg_match('/^(een|één|1)( jaar|j| uur|u)/', $interval)) {
+ return "elk $output";
+ }
+
+ return "elke $output";
+ },
+ 'period_start_date' => 'van :date',
+ 'period_end_date' => 'tot :date',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD-MM-YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[vandaag om] LT',
+ 'nextDay' => '[morgen om] LT',
+ 'nextWeek' => 'dddd [om] LT',
+ 'lastDay' => '[gisteren om] LT',
+ 'lastWeek' => '[afgelopen] dddd [om] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de');
+ },
+ 'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
+ 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
+ 'mmm_suffix' => '.',
+ 'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
+ 'weekdays_short' => ['zo.', 'ma.', 'di.', 'wo.', 'do.', 'vr.', 'za.'],
+ 'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' en '],
+ 'meridiem' => ['\'s ochtends', '\'s middags'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_AW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_AW.php
new file mode 100644
index 0000000..5ec136d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_AW.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/nl.php', [
+ 'formats' => [
+ 'L' => 'DD-MM-YY',
+ ],
+ 'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
+ 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
+ 'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
+ 'weekdays_short' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
+ 'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_BE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_BE.php
new file mode 100644
index 0000000..037f5b4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_BE.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Roy
+ * - Stephan
+ * - François B
+ * - Tim Fish
+ * - Kevin Huang
+ * - Jacob Middag
+ * - JD Isaacks
+ * - Propaganistas
+ */
+return array_replace_recursive(require __DIR__.'/nl.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_BQ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_BQ.php
new file mode 100644
index 0000000..521d2d6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_BQ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/nl.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_CW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_CW.php
new file mode 100644
index 0000000..521d2d6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_CW.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/nl.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_NL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_NL.php
new file mode 100644
index 0000000..14e4853
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_NL.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/nl.php', [
+ 'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
+ 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
+ 'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
+ 'weekdays_short' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
+ 'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_SR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_SR.php
new file mode 100644
index 0000000..521d2d6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_SR.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/nl.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_SX.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_SX.php
new file mode 100644
index 0000000..521d2d6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl_SX.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/nl.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nmg.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nmg.php
new file mode 100644
index 0000000..f8850e2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nmg.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['maná', 'kugú'],
+ 'weekdays' => ['sɔ́ndɔ', 'mɔ́ndɔ', 'sɔ́ndɔ mafú mába', 'sɔ́ndɔ mafú málal', 'sɔ́ndɔ mafú mána', 'mabágá má sukul', 'sásadi'],
+ 'weekdays_short' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'mbs', 'sas'],
+ 'weekdays_min' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'mbs', 'sas'],
+ 'months' => ['ngwɛn matáhra', 'ngwɛn ńmba', 'ngwɛn ńlal', 'ngwɛn ńna', 'ngwɛn ńtan', 'ngwɛn ńtuó', 'ngwɛn hɛmbuɛrí', 'ngwɛn lɔmbi', 'ngwɛn rɛbvuâ', 'ngwɛn wum', 'ngwɛn wum navǔr', 'krísimin'],
+ 'months_short' => ['ng1', 'ng2', 'ng3', 'ng4', 'ng5', 'ng6', 'ng7', 'ng8', 'ng9', 'ng10', 'ng11', 'kris'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nn.php
new file mode 100644
index 0000000..041f7b2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nn.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Alexander Tømmerås
+ * - Øystein
+ * - JD Isaacks
+ * - Gaute Hvoslef Kvalnes (gaute)
+ */
+return [
+ 'year' => ':count år',
+ 'a_year' => 'eit år|:count år',
+ 'y' => ':count år',
+ 'month' => ':count månad|:count månader',
+ 'a_month' => 'ein månad|:count månader',
+ 'm' => ':count md',
+ 'week' => ':count veke|:count veker',
+ 'a_week' => 'ei veke|:count veker',
+ 'w' => ':countv',
+ 'day' => ':count dag|:count dagar',
+ 'a_day' => 'ein dag|:count dagar',
+ 'd' => ':countd',
+ 'hour' => ':count time|:count timar',
+ 'a_hour' => 'ein time|:count timar',
+ 'h' => ':countt',
+ 'minute' => ':count minutt',
+ 'a_minute' => 'eit minutt|:count minutt',
+ 'min' => ':countm',
+ 'second' => ':count sekund',
+ 'a_second' => 'nokre sekund|:count sekund',
+ 's' => ':counts',
+ 'ago' => ':time sidan',
+ 'from_now' => 'om :time',
+ 'after' => ':time etter',
+ 'before' => ':time før',
+ 'diff_today' => 'I dag',
+ 'diff_yesterday' => 'I går',
+ 'diff_yesterday_regexp' => 'I går(?:\\s+klokka)?',
+ 'diff_tomorrow' => 'I morgon',
+ 'diff_tomorrow_regexp' => 'I morgon(?:\\s+klokka)?',
+ 'diff_today_regexp' => 'I dag(?:\\s+klokka)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY [kl.] H:mm',
+ 'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[I dag klokka] LT',
+ 'nextDay' => '[I morgon klokka] LT',
+ 'nextWeek' => 'dddd [klokka] LT',
+ 'lastDay' => '[I går klokka] LT',
+ 'lastWeek' => '[Føregåande] dddd [klokka] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
+ 'weekdays' => ['sundag', 'måndag', 'tysdag', 'onsdag', 'torsdag', 'fredag', 'laurdag'],
+ 'weekdays_short' => ['sun', 'mån', 'tys', 'ons', 'tor', 'fre', 'lau'],
+ 'weekdays_min' => ['su', 'må', 'ty', 'on', 'to', 'fr', 'la'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' og '],
+ 'meridiem' => ['f.m.', 'e.m.'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nn_NO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nn_NO.php
new file mode 100644
index 0000000..ebbe0b7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nn_NO.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/nn.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nnh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nnh.php
new file mode 100644
index 0000000..fa6a448
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nnh.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['mbaʼámbaʼ', 'ncwònzém'],
+ 'weekdays' => null,
+ 'weekdays_short' => ['lyɛʼɛ́ sẅíŋtè', 'mvfò lyɛ̌ʼ', 'mbɔ́ɔntè mvfò lyɛ̌ʼ', 'tsètsɛ̀ɛ lyɛ̌ʼ', 'mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ', 'mvfò màga lyɛ̌ʼ', 'màga lyɛ̌ʼ'],
+ 'weekdays_min' => null,
+ 'months' => null,
+ 'months_short' => ['saŋ tsetsɛ̀ɛ lùm', 'saŋ kàg ngwóŋ', 'saŋ lepyè shúm', 'saŋ cÿó', 'saŋ tsɛ̀ɛ cÿó', 'saŋ njÿoláʼ', 'saŋ tyɛ̀b tyɛ̀b mbʉ̀ŋ', 'saŋ mbʉ̀ŋ', 'saŋ ngwɔ̀ʼ mbÿɛ', 'saŋ tàŋa tsetsáʼ', 'saŋ mejwoŋó', 'saŋ lùm'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/yy',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => '[lyɛ]̌ʼ d [na] MMMM, YYYY HH:mm',
+ 'LLLL' => 'dddd , [lyɛ]̌ʼ d [na] MMMM, YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/no.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/no.php
new file mode 100644
index 0000000..f4497c7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/no.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Daniel S. Billing
+ * - Paul
+ * - Jimmie Johansson
+ * - Jens Herlevsen
+ */
+return array_replace_recursive(require __DIR__.'/nb.php', [
+ 'formats' => [
+ 'LLL' => 'D. MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY [kl.] HH:mm',
+ ],
+ 'calendar' => [
+ 'nextWeek' => 'på dddd [kl.] LT',
+ 'lastWeek' => '[i] dddd[s kl.] LT',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nr.php
new file mode 100644
index 0000000..1bc999f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nr.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/nr_ZA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nr_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nr_ZA.php
new file mode 100644
index 0000000..f9a7be8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nr_ZA.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Janabari', 'uFeberbari', 'uMatjhi', 'u-Apreli', 'Meyi', 'Juni', 'Julayi', 'Arhostosi', 'Septemba', 'Oktoba', 'Usinyikhaba', 'Disemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mat', 'Apr', 'Mey', 'Jun', 'Jul', 'Arh', 'Sep', 'Okt', 'Usi', 'Dis'],
+ 'weekdays' => ['uSonto', 'uMvulo', 'uLesibili', 'lesithathu', 'uLesine', 'ngoLesihlanu', 'umGqibelo'],
+ 'weekdays_short' => ['Son', 'Mvu', 'Bil', 'Tha', 'Ne', 'Hla', 'Gqi'],
+ 'weekdays_min' => ['Son', 'Mvu', 'Bil', 'Tha', 'Ne', 'Hla', 'Gqi'],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nso.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nso.php
new file mode 100644
index 0000000..2a6cabb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nso.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/nso_ZA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nso_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nso_ZA.php
new file mode 100644
index 0000000..b08fe6d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nso_ZA.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Janaware', 'Febereware', 'Matšhe', 'Aprele', 'Mei', 'June', 'Julae', 'Agostose', 'Setemere', 'Oktobere', 'Nofemere', 'Disemere'],
+ 'months_short' => ['Jan', 'Feb', 'Mat', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Set', 'Okt', 'Nof', 'Dis'],
+ 'weekdays' => ['LaMorena', 'Mošupologo', 'Labobedi', 'Laboraro', 'Labone', 'Labohlano', 'Mokibelo'],
+ 'weekdays_short' => ['Son', 'Moš', 'Bed', 'Rar', 'Ne', 'Hla', 'Mok'],
+ 'weekdays_min' => ['Son', 'Moš', 'Bed', 'Rar', 'Ne', 'Hla', 'Mok'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count ngwaga',
+ 'y' => ':count ngwaga',
+ 'a_year' => ':count ngwaga',
+
+ 'month' => ':count Kgwedi',
+ 'm' => ':count Kgwedi',
+ 'a_month' => ':count Kgwedi',
+
+ 'week' => ':count Beke',
+ 'w' => ':count Beke',
+ 'a_week' => ':count Beke',
+
+ 'day' => ':count Letšatši',
+ 'd' => ':count Letšatši',
+ 'a_day' => ':count Letšatši',
+
+ 'hour' => ':count Iri',
+ 'h' => ':count Iri',
+ 'a_hour' => ':count Iri',
+
+ 'minute' => ':count Motsotso',
+ 'min' => ':count Motsotso',
+ 'a_minute' => ':count Motsotso',
+
+ 'second' => ':count motsotswana',
+ 's' => ':count motsotswana',
+ 'a_second' => ':count motsotswana',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nus.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nus.php
new file mode 100644
index 0000000..033e975
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nus.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['RW', 'TŊ'],
+ 'weekdays' => ['Cäŋ kuɔth', 'Jiec la̱t', 'Rɛw lätni', 'Diɔ̱k lätni', 'Ŋuaan lätni', 'Dhieec lätni', 'Bäkɛl lätni'],
+ 'weekdays_short' => ['Cäŋ', 'Jiec', 'Rɛw', 'Diɔ̱k', 'Ŋuaan', 'Dhieec', 'Bäkɛl'],
+ 'weekdays_min' => ['Cäŋ', 'Jiec', 'Rɛw', 'Diɔ̱k', 'Ŋuaan', 'Dhieec', 'Bäkɛl'],
+ 'months' => ['Tiop thar pɛt', 'Pɛt', 'Duɔ̱ɔ̱ŋ', 'Guak', 'Duät', 'Kornyoot', 'Pay yie̱tni', 'Tho̱o̱r', 'Tɛɛr', 'Laath', 'Kur', 'Tio̱p in di̱i̱t'],
+ 'months_short' => ['Tiop', 'Pɛt', 'Duɔ̱ɔ̱', 'Guak', 'Duä', 'Kor', 'Pay', 'Thoo', 'Tɛɛ', 'Laa', 'Kur', 'Tid'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'D/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd D MMMM YYYY h:mm a',
+ ],
+
+ 'year' => ':count jiök', // less reliable
+ 'y' => ':count jiök', // less reliable
+ 'a_year' => ':count jiök', // less reliable
+
+ 'month' => ':count pay', // less reliable
+ 'm' => ':count pay', // less reliable
+ 'a_month' => ':count pay', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nyn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nyn.php
new file mode 100644
index 0000000..fdc2ff4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nyn.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'weekdays' => ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu', 'Orwakana', 'Orwakataano', 'Orwamukaaga'],
+ 'weekdays_short' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
+ 'weekdays_min' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
+ 'months' => ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana', 'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda', 'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'],
+ 'months_short' => ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS', 'KMN', 'KMW', 'KKM', 'KNK', 'KNB'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/oc.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/oc.php
new file mode 100644
index 0000000..94c3e04
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/oc.php
@@ -0,0 +1,98 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Quentí
+ */
+// @codeCoverageIgnoreStart
+if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) {
+ \Symfony\Component\Translation\PluralizationRules::set(function ($number) {
+ return $number == 1 ? 0 : 1;
+ }, 'oc');
+}
+// @codeCoverageIgnoreEnd
+
+return [
+ 'year' => ':count an|:count ans',
+ 'a_year' => 'un an|:count ans',
+ 'y' => ':count an|:count ans',
+ 'month' => ':count mes|:count meses',
+ 'a_month' => 'un mes|:count meses',
+ 'm' => ':count mes|:count meses',
+ 'week' => ':count setmana|:count setmanas',
+ 'a_week' => 'una setmana|:count setmanas',
+ 'w' => ':count setmana|:count setmanas',
+ 'day' => ':count jorn|:count jorns',
+ 'a_day' => 'un jorn|:count jorns',
+ 'd' => ':count jorn|:count jorns',
+ 'hour' => ':count ora|:count oras',
+ 'a_hour' => 'una ora|:count oras',
+ 'h' => ':count ora|:count oras',
+ 'minute' => ':count minuta|:count minutas',
+ 'a_minute' => 'una minuta|:count minutas',
+ 'min' => ':count minuta|:count minutas',
+ 'second' => ':count segonda|:count segondas',
+ 'a_second' => 'una segonda|:count segondas',
+ 's' => ':count segonda|:count segondas',
+ 'ago' => 'fa :time',
+ 'from_now' => 'd\'aquí :time',
+ 'after' => ':time aprèp',
+ 'before' => ':time abans',
+ 'diff_now' => 'ara meteis',
+ 'diff_today' => 'Uèi',
+ 'diff_today_regexp' => 'Uèi(?:\\s+a)?',
+ 'diff_yesterday' => 'ièr',
+ 'diff_yesterday_regexp' => 'Ièr(?:\\s+a)?',
+ 'diff_tomorrow' => 'deman',
+ 'diff_tomorrow_regexp' => 'Deman(?:\\s+a)?',
+ 'diff_before_yesterday' => 'ièr delà',
+ 'diff_after_tomorrow' => 'deman passat',
+ 'period_recurrences' => ':count còp|:count còps',
+ 'period_interval' => 'cada :interval',
+ 'period_start_date' => 'de :date',
+ 'period_end_date' => 'fins a :date',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM [de] YYYY',
+ 'LLL' => 'D MMMM [de] YYYY [a] H:mm',
+ 'LLLL' => 'dddd D MMMM [de] YYYY [a] H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Uèi a] LT',
+ 'nextDay' => '[Deman a] LT',
+ 'nextWeek' => 'dddd [a] LT',
+ 'lastDay' => '[Ièr a] LT',
+ 'lastWeek' => 'dddd [passat a] LT',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['de genièr', 'de febrièr', 'de març', 'd\'abrial', 'de mai', 'de junh', 'de julhet', 'd\'agost', 'de setembre', 'd’octòbre', 'de novembre', 'de decembre'],
+ 'months_standalone' => ['genièr', 'febrièr', 'març', 'abrial', 'mai', 'junh', 'julh', 'agost', 'setembre', 'octòbre', 'novembre', 'decembre'],
+ 'months_short' => ['gen.', 'feb.', 'març', 'abr.', 'mai', 'junh', 'julh', 'ago.', 'sep.', 'oct.', 'nov.', 'dec.'],
+ 'weekdays' => ['dimenge', 'diluns', 'dimars', 'dimècres', 'dijòus', 'divendres', 'dissabte'],
+ 'weekdays_short' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'],
+ 'weekdays_min' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'],
+ 'ordinal' => function ($number, string $period = '') {
+ $ordinal = [1 => 'èr', 2 => 'nd'][(int) $number] ?? 'en';
+
+ // feminine for year, week, hour, minute, second
+ if (preg_match('/^[yYwWhHgGis]$/', $period)) {
+ $ordinal .= 'a';
+ }
+
+ return $number.$ordinal;
+ },
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' e '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/oc_FR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/oc_FR.php
new file mode 100644
index 0000000..fde859f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/oc_FR.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/oc.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/om.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/om.php
new file mode 100644
index 0000000..b8d5a0b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/om.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation & Sagalee Oromoo Publishing Co. Inc. locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'dd-MMM-YYYY',
+ 'LLL' => 'dd MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, MMMM D, YYYY HH:mm',
+ ],
+ 'months' => ['Amajjii', 'Guraandhala', 'Bitooteessa', 'Elba', 'Caamsa', 'Waxabajjii', 'Adooleessa', 'Hagayya', 'Fuulbana', 'Onkololeessa', 'Sadaasa', 'Muddee'],
+ 'months_short' => ['Ama', 'Gur', 'Bit', 'Elb', 'Cam', 'Wax', 'Ado', 'Hag', 'Ful', 'Onk', 'Sad', 'Mud'],
+ 'weekdays' => ['Dilbata', 'Wiixata', 'Qibxata', 'Roobii', 'Kamiisa', 'Jimaata', 'Sanbata'],
+ 'weekdays_short' => ['Dil', 'Wix', 'Qib', 'Rob', 'Kam', 'Jim', 'San'],
+ 'weekdays_min' => ['Dil', 'Wix', 'Qib', 'Rob', 'Kam', 'Jim', 'San'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['WD', 'WB'],
+
+ 'year' => 'wggoota :count',
+ 'y' => 'wggoota :count',
+ 'a_year' => 'wggoota :count',
+
+ 'month' => 'ji’a :count',
+ 'm' => 'ji’a :count',
+ 'a_month' => 'ji’a :count',
+
+ 'week' => 'torban :count',
+ 'w' => 'torban :count',
+ 'a_week' => 'torban :count',
+
+ 'day' => 'guyyaa :count',
+ 'd' => 'guyyaa :count',
+ 'a_day' => 'guyyaa :count',
+
+ 'hour' => 'saʼaatii :count',
+ 'h' => 'saʼaatii :count',
+ 'a_hour' => 'saʼaatii :count',
+
+ 'minute' => 'daqiiqaa :count',
+ 'min' => 'daqiiqaa :count',
+ 'a_minute' => 'daqiiqaa :count',
+
+ 'second' => 'sekoondii :count',
+ 's' => 'sekoondii :count',
+ 'a_second' => 'sekoondii :count',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/om_ET.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/om_ET.php
new file mode 100644
index 0000000..4648343
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/om_ET.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/om.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/om_KE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/om_KE.php
new file mode 100644
index 0000000..b29a40f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/om_KE.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/om.php', [
+ 'day_of_first_week_of_year' => 0,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/or.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/or.php
new file mode 100644
index 0000000..3aa7173
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/or.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/or_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/or_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/or_IN.php
new file mode 100644
index 0000000..57a89f5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/or_IN.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM AP Linux Technology Center, Yamato Software Laboratory bug-glibc@gnu.org
+ */
+return [
+ 'diff_now' => 'ବର୍ତ୍ତମାନ',
+ 'diff_yesterday' => 'ଗତକାଲି',
+ 'diff_tomorrow' => 'ଆସନ୍ତାକାଲି',
+ 'formats' => [
+ 'LT' => 'Oh:Om A',
+ 'LTS' => 'Oh:Om:Os A',
+ 'L' => 'OD-OM-OY',
+ 'LL' => 'OD MMMM OY',
+ 'LLL' => 'OD MMMM OY Oh:Om A',
+ 'LLLL' => 'dddd OD MMMM OY Oh:Om A',
+ ],
+ 'months' => ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ', 'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ', 'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର', 'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର', 'ଡିସେମ୍ବର'],
+ 'months_short' => ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ', 'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ', 'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର', 'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର', 'ଡିସେମ୍ବର'],
+ 'weekdays' => ['ରବିବାର', 'ସୋମବାର', 'ମଙ୍ଗଳବାର', 'ବୁଧବାର', 'ଗୁରୁବାର', 'ଶୁକ୍ରବାର', 'ଶନିବାର'],
+ 'weekdays_short' => ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ', 'ବୁଧ', 'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'],
+ 'weekdays_min' => ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ', 'ବୁଧ', 'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'],
+ 'day_of_first_week_of_year' => 1,
+ 'alt_numbers' => ['୦', '୧', '୨', '୩', '୪', '୫', '୬', '୭', '୮', '୯', '୧୦', '୧୧', '୧୨', '୧୩', '୧୪', '୧୫', '୧୬', '୧୭', '୧୮', '୧୯', '୨୦', '୨୧', '୨୨', '୨୩', '୨୪', '୨୫', '୨୬', '୨୭', '୨୮', '୨୯', '୩୦', '୩୧', '୩୨', '୩୩', '୩୪', '୩୫', '୩୬', '୩୭', '୩୮', '୩୯', '୪୦', '୪୧', '୪୨', '୪୩', '୪୪', '୪୫', '୪୬', '୪୭', '୪୮', '୪୯', '୫୦', '୫୧', '୫୨', '୫୩', '୫୪', '୫୫', '୫୬', '୫୭', '୫୮', '୫୯', '୬୦', '୬୧', '୬୨', '୬୩', '୬୪', '୬୫', '୬୬', '୬୭', '୬୮', '୬୯', '୭୦', '୭୧', '୭୨', '୭୩', '୭୪', '୭୫', '୭୬', '୭୭', '୭୮', '୭୯', '୮୦', '୮୧', '୮୨', '୮୩', '୮୪', '୮୫', '୮୬', '୮୭', '୮୮', '୮୯', '୯୦', '୯୧', '୯୨', '୯୩', '୯୪', '୯୫', '୯୬', '୯୭', '୯୮', '୯୯'],
+ 'year' => ':count ବର୍ଷ',
+ 'y' => ':count ବ.',
+ 'month' => ':count ମାସ',
+ 'm' => ':count ମା.',
+ 'week' => ':count ସପ୍ତାହ',
+ 'w' => ':count ସପ୍ତା.',
+ 'day' => ':count ଦିନ',
+ 'd' => ':count ଦିନ',
+ 'hour' => ':count ଘଣ୍ତ',
+ 'h' => ':count ଘ.',
+ 'minute' => ':count ମିନଟ',
+ 'min' => ':count ମି.',
+ 'second' => ':count ସେକଣ୍ଢ',
+ 's' => ':count ସେ.',
+ 'ago' => ':time ପୂର୍ବେ',
+ 'from_now' => ':timeରେ',
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/os.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/os.php
new file mode 100644
index 0000000..5f55e8a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/os.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/os_RU.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/os_RU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/os_RU.php
new file mode 100644
index 0000000..9592d15
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/os_RU.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['январы', 'февралы', 'мартъийы', 'апрелы', 'майы', 'июны', 'июлы', 'августы', 'сентябры', 'октябры', 'ноябры', 'декабры'],
+ 'months_short' => ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
+ 'weekdays' => ['Хуыцаубон', 'Къуырисæр', 'Дыццæг', 'Æртыццæг', 'Цыппæрæм', 'Майрæмбон', 'Сабат'],
+ 'weekdays_short' => ['Хцб', 'Крс', 'Дцг', 'Æрт', 'Цпр', 'Мрб', 'Сбт'],
+ 'weekdays_min' => ['Хцб', 'Крс', 'Дцг', 'Æрт', 'Цпр', 'Мрб', 'Сбт'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'minute' => ':count гыццыл', // less reliable
+ 'min' => ':count гыццыл', // less reliable
+ 'a_minute' => ':count гыццыл', // less reliable
+
+ 'second' => ':count æндæр', // less reliable
+ 's' => ':count æндæр', // less reliable
+ 'a_second' => ':count æндæр', // less reliable
+
+ 'year' => ':count аз',
+ 'y' => ':count аз',
+ 'a_year' => ':count аз',
+
+ 'month' => ':count мӕй',
+ 'm' => ':count мӕй',
+ 'a_month' => ':count мӕй',
+
+ 'week' => ':count къуыри',
+ 'w' => ':count къуыри',
+ 'a_week' => ':count къуыри',
+
+ 'day' => ':count бон',
+ 'd' => ':count бон',
+ 'a_day' => ':count бон',
+
+ 'hour' => ':count сахат',
+ 'h' => ':count сахат',
+ 'a_hour' => ':count сахат',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa.php
new file mode 100644
index 0000000..48b2033
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - Tsutomu Kuroda
+ * - Punjab
+ */
+return [
+ 'year' => 'ਇੱਕ ਸਾਲ|:count ਸਾਲ',
+ 'month' => 'ਇੱਕ ਮਹੀਨਾ|:count ਮਹੀਨੇ',
+ 'week' => 'ਹਫਤਾ|:count ਹਫ਼ਤੇ',
+ 'day' => 'ਇੱਕ ਦਿਨ|:count ਦਿਨ',
+ 'hour' => 'ਇੱਕ ਘੰਟਾ|:count ਘੰਟੇ',
+ 'minute' => 'ਇਕ ਮਿੰਟ|:count ਮਿੰਟ',
+ 'second' => 'ਕੁਝ ਸਕਿੰਟ|:count ਸਕਿੰਟ',
+ 'ago' => ':time ਪਹਿਲਾਂ',
+ 'from_now' => ':time ਵਿੱਚ',
+ 'before' => ':time ਤੋਂ ਪਹਿਲਾਂ',
+ 'after' => ':time ਤੋਂ ਬਾਅਦ',
+ 'diff_now' => 'ਹੁਣ',
+ 'diff_today' => 'ਅਜ',
+ 'diff_yesterday' => 'ਕਲ',
+ 'diff_tomorrow' => 'ਕਲ',
+ 'formats' => [
+ 'LT' => 'A h:mm ਵਜੇ',
+ 'LTS' => 'A h:mm:ss ਵਜੇ',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, A h:mm ਵਜੇ',
+ 'LLLL' => 'dddd, D MMMM YYYY, A h:mm ਵਜੇ',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[ਅਜ] LT',
+ 'nextDay' => '[ਕਲ] LT',
+ 'nextWeek' => '[ਅਗਲਾ] dddd, LT',
+ 'lastDay' => '[ਕਲ] LT',
+ 'lastWeek' => '[ਪਿਛਲੇ] dddd, LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'ਰਾਤ';
+ }
+ if ($hour < 10) {
+ return 'ਸਵੇਰ';
+ }
+ if ($hour < 17) {
+ return 'ਦੁਪਹਿਰ';
+ }
+ if ($hour < 20) {
+ return 'ਸ਼ਾਮ';
+ }
+
+ return 'ਰਾਤ';
+ },
+ 'months' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'],
+ 'months_short' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'],
+ 'weekdays' => ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ', 'ਮੰਗਲਵਾਰ', 'ਬੁਧਵਾਰ', 'ਵੀਰਵਾਰ', 'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨੀਚਰਵਾਰ'],
+ 'weekdays_short' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁਧ', 'ਵੀਰ', 'ਸ਼ੁਕਰ', 'ਸ਼ਨੀ'],
+ 'weekdays_min' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁਧ', 'ਵੀਰ', 'ਸ਼ੁਕਰ', 'ਸ਼ਨੀ'],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' ਅਤੇ '],
+ 'weekend' => [0, 0],
+ 'alt_numbers' => ['੦', '੧', '੨', '੩', '੪', '੫', '੬', '੭', '੮', '੯'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_Arab.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_Arab.php
new file mode 100644
index 0000000..8b04dee
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_Arab.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ur.php', [
+ 'weekdays' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'],
+ 'weekdays_short' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'],
+ 'weekdays_min' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'],
+ 'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئ', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئ', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd, DD MMMM YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_Guru.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_Guru.php
new file mode 100644
index 0000000..c0d35ec
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_Guru.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/pa.php', [
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'D/M/yy',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY, h:mm a',
+ 'LLLL' => 'dddd, D MMMM YYYY, h:mm a',
+ ],
+ 'months' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'],
+ 'months_short' => ['ਜਨ', 'ਫ਼ਰ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾ', 'ਅਗ', 'ਸਤੰ', 'ਅਕਤੂ', 'ਨਵੰ', 'ਦਸੰ'],
+ 'weekdays' => ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ', 'ਮੰਗਲਵਾਰ', 'ਬੁੱਧਵਾਰ', 'ਵੀਰਵਾਰ', 'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨਿੱਚਰਵਾਰ'],
+ 'weekdays_short' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕਰ', 'ਸ਼ਨਿੱਚਰ'],
+ 'weekdays_min' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗ', 'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕ', 'ਸ਼ਨਿੱ'],
+ 'weekend' => [0, 0],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_IN.php
new file mode 100644
index 0000000..ca67642
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_IN.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Guo Xiang Tan
+ * - Josh Soref
+ * - Ash
+ * - harpreetkhalsagtbit
+ */
+return require __DIR__.'/pa.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_PK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_PK.php
new file mode 100644
index 0000000..f9af11c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pa_PK.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['جنوري', 'فروري', 'مارچ', 'اپريل', 'مٓی', 'جون', 'جولاي', 'اگست', 'ستمبر', 'اكتوبر', 'نومبر', 'دسمبر'],
+ 'months_short' => ['جنوري', 'فروري', 'مارچ', 'اپريل', 'مٓی', 'جون', 'جولاي', 'اگست', 'ستمبر', 'اكتوبر', 'نومبر', 'دسمبر'],
+ 'weekdays' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
+ 'weekdays_short' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
+ 'weekdays_min' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ص', 'ش'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pap.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pap.php
new file mode 100644
index 0000000..b4c1706
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pap.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return [
+ 'formats' => [
+ 'LT' => 'HH.mm',
+ 'LTS' => 'HH.mm:ss',
+ 'L' => 'DD-MM-YY',
+ 'LL' => 'MMMM [di] DD, YYYY',
+ 'LLL' => 'DD MMM HH.mm',
+ 'LLLL' => 'MMMM DD, YYYY HH.mm',
+ ],
+ 'months' => ['yanüari', 'febrüari', 'mart', 'aprel', 'mei', 'yüni', 'yüli', 'ougùstùs', 'sèptèmber', 'oktober', 'novèmber', 'desèmber'],
+ 'months_short' => ['yan', 'feb', 'mar', 'apr', 'mei', 'yün', 'yül', 'oug', 'sèp', 'okt', 'nov', 'des'],
+ 'weekdays' => ['djadomingo', 'djaluna', 'djamars', 'djawebs', 'djarason', 'djabierne', 'djasabra'],
+ 'weekdays_short' => ['do', 'lu', 'ma', 'we', 'ra', 'bi', 'sa'],
+ 'weekdays_min' => ['do', 'lu', 'ma', 'we', 'ra', 'bi', 'sa'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'year' => ':count aña',
+ 'month' => ':count luna',
+ 'week' => ':count siman',
+ 'day' => ':count dia',
+ 'hour' => ':count ora',
+ 'minute' => ':count minüt',
+ 'second' => ':count sekònde',
+ 'list' => [', ', ' i '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pap_AW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pap_AW.php
new file mode 100644
index 0000000..e9a48ff
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pap_AW.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - information from native speaker Pablo Saratxaga pablo@mandrakesoft.com
+ */
+return require __DIR__.'/pap.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pap_CW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pap_CW.php
new file mode 100644
index 0000000..e9a48ff
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pap_CW.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - information from native speaker Pablo Saratxaga pablo@mandrakesoft.com
+ */
+return require __DIR__.'/pap.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pl.php
new file mode 100644
index 0000000..ca10fe4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pl.php
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Wacław Jacek
+ * - François B
+ * - Tim Fish
+ * - Serhan Apaydın
+ * - Massimiliano Caniparoli
+ * - JD Isaacks
+ * - Jakub Szwacz
+ * - Jan
+ * - Paul
+ * - damlys
+ * - Marek (marast78)
+ * - Peter (UnrulyNatives)
+ * - Qrzysio
+ * - Jan (aso824)
+ */
+return [
+ 'year' => ':count rok|:count lata|:count lat',
+ 'a_year' => 'rok|:count lata|:count lat',
+ 'y' => ':count r|:count l|:count l',
+ 'month' => ':count miesiąc|:count miesiące|:count miesięcy',
+ 'a_month' => 'miesiąc|:count miesiące|:count miesięcy',
+ 'm' => ':count mies.',
+ 'week' => ':count tydzień|:count tygodnie|:count tygodni',
+ 'a_week' => 'tydzień|:count tygodnie|:count tygodni',
+ 'w' => ':count tyg.',
+ 'day' => ':count dzień|:count dni|:count dni',
+ 'a_day' => 'dzień|:count dni|:count dni',
+ 'd' => ':count d',
+ 'hour' => ':count godzina|:count godziny|:count godzin',
+ 'a_hour' => 'godzina|:count godziny|:count godzin',
+ 'h' => ':count godz.',
+ 'minute' => ':count minuta|:count minuty|:count minut',
+ 'a_minute' => 'minuta|:count minuty|:count minut',
+ 'min' => ':count min.',
+ 'second' => ':count sekunda|:count sekundy|:count sekund',
+ 'a_second' => '{1}kilka sekund|:count sekunda|:count sekundy|:count sekund',
+ 's' => ':count sek.',
+ 'ago' => ':time temu',
+ 'from_now' => 'za :time',
+ 'after' => ':time po',
+ 'before' => ':time przed',
+ 'diff_now' => 'przed chwilą',
+ 'diff_today' => 'Dziś',
+ 'diff_today_regexp' => 'Dziś(?:\\s+o)?',
+ 'diff_yesterday' => 'wczoraj',
+ 'diff_yesterday_regexp' => 'Wczoraj(?:\\s+o)?',
+ 'diff_tomorrow' => 'jutro',
+ 'diff_tomorrow_regexp' => 'Jutro(?:\\s+o)?',
+ 'diff_before_yesterday' => 'przedwczoraj',
+ 'diff_after_tomorrow' => 'pojutrze',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Dziś o] LT',
+ 'nextDay' => '[Jutro o] LT',
+ 'nextWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[W niedzielę o] LT';
+ case 2:
+ return '[We wtorek o] LT';
+ case 3:
+ return '[W środę o] LT';
+ case 6:
+ return '[W sobotę o] LT';
+ default:
+ return '[W] dddd [o] LT';
+ }
+ },
+ 'lastDay' => '[Wczoraj o] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[W zeszłą niedzielę o] LT';
+ case 3:
+ return '[W zeszłą środę o] LT';
+ case 6:
+ return '[W zeszłą sobotę o] LT';
+ default:
+ return '[W zeszły] dddd [o] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['stycznia', 'lutego', 'marca', 'kwietnia', 'maja', 'czerwca', 'lipca', 'sierpnia', 'września', 'października', 'listopada', 'grudnia'],
+ 'months_standalone' => ['styczeń', 'luty', 'marzec', 'kwiecień', 'maj', 'czerwiec', 'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad', 'grudzień'],
+ 'months_short' => ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip', 'sie', 'wrz', 'paź', 'lis', 'gru'],
+ 'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
+ 'weekdays' => ['niedziela', 'poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota'],
+ 'weekdays_short' => ['ndz', 'pon', 'wt', 'śr', 'czw', 'pt', 'sob'],
+ 'weekdays_min' => ['Nd', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'So'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' i '],
+ 'meridiem' => ['przed południem', 'po południu'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pl_PL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pl_PL.php
new file mode 100644
index 0000000..69cd697
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pl_PL.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/pl.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/prg.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/prg.php
new file mode 100644
index 0000000..d0fd2f0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/prg.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
+ 'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-dd',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'YYYY MMMM D HH:mm',
+ 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
+ ],
+
+ 'year' => ':count meta',
+ 'y' => ':count meta',
+ 'a_year' => ':count meta',
+
+ 'month' => ':count mēniks', // less reliable
+ 'm' => ':count mēniks', // less reliable
+ 'a_month' => ':count mēniks', // less reliable
+
+ 'week' => ':count sawaītin', // less reliable
+ 'w' => ':count sawaītin', // less reliable
+ 'a_week' => ':count sawaītin', // less reliable
+
+ 'day' => ':count di',
+ 'd' => ':count di',
+ 'a_day' => ':count di',
+
+ 'hour' => ':count bruktēt', // less reliable
+ 'h' => ':count bruktēt', // less reliable
+ 'a_hour' => ':count bruktēt', // less reliable
+
+ 'minute' => ':count līkuts', // less reliable
+ 'min' => ':count līkuts', // less reliable
+ 'a_minute' => ':count līkuts', // less reliable
+
+ 'second' => ':count kitan', // less reliable
+ 's' => ':count kitan', // less reliable
+ 'a_second' => ':count kitan', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ps.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ps.php
new file mode 100644
index 0000000..a928b28
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ps.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Muhammad Nasir Rahimi
+ * - Nassim Nasibullah (spinzar)
+ */
+return [
+ 'year' => ':count کال|:count کاله',
+ 'y' => ':countکال|:countکاله',
+ 'month' => ':count مياشت|:count مياشتي',
+ 'm' => ':countمياشت|:countمياشتي',
+ 'week' => ':count اونۍ|:count اونۍ',
+ 'w' => ':countاونۍ|:countاونۍ',
+ 'day' => ':count ورځ|:count ورځي',
+ 'd' => ':countورځ|:countورځي',
+ 'hour' => ':count ساعت|:count ساعته',
+ 'h' => ':countساعت|:countساعته',
+ 'minute' => ':count دقيقه|:count دقيقې',
+ 'min' => ':countدقيقه|:countدقيقې',
+ 'second' => ':count ثانيه|:count ثانيې',
+ 's' => ':countثانيه|:countثانيې',
+ 'ago' => ':time دمخه',
+ 'from_now' => ':time له اوس څخه',
+ 'after' => ':time وروسته',
+ 'before' => ':time دمخه',
+ 'list' => ['، ', ' او '],
+ 'meridiem' => ['غ.م.', 'غ.و.'],
+ 'weekdays' => ['اتوار', 'ګل', 'نهه', 'شورو', 'زيارت', 'جمعه', 'خالي'],
+ 'weekdays_short' => ['ا', 'ګ', 'ن', 'ش', 'ز', 'ج', 'خ'],
+ 'weekdays_min' => ['ا', 'ګ', 'ن', 'ش', 'ز', 'ج', 'خ'],
+ 'months' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سېپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'months_short' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سېپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'months_standalone' => ['جنوري', 'فېبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'months_short_standalone' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'first_day_of_week' => 6,
+ 'weekend' => [4, 5],
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'YYYY/M/d',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'د YYYY د MMMM D H:mm',
+ 'LLLL' => 'dddd د YYYY د MMMM D H:mm',
+ ],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ps_AF.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ps_AF.php
new file mode 100644
index 0000000..e63121e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ps_AF.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ps.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt.php
new file mode 100644
index 0000000..e36ca4c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt.php
@@ -0,0 +1,104 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Cassiano Montanari
+ * - Matt Pope
+ * - François B
+ * - Prodis
+ * - JD Isaacks
+ * - Raphael Amorim
+ * - João Magalhães
+ * - victortobias
+ * - Paulo Freitas
+ * - Sebastian Thierer
+ * - Claudson Martins (claudsonm)
+ */
+return [
+ 'year' => ':count ano|:count anos',
+ 'a_year' => 'um ano|:count anos',
+ 'y' => ':counta',
+ 'month' => ':count mês|:count meses',
+ 'a_month' => 'um mês|:count meses',
+ 'm' => ':countm',
+ 'week' => ':count semana|:count semanas',
+ 'a_week' => 'uma semana|:count semanas',
+ 'w' => ':countsem',
+ 'day' => ':count dia|:count dias',
+ 'a_day' => 'um dia|:count dias',
+ 'd' => ':countd',
+ 'hour' => ':count hora|:count horas',
+ 'a_hour' => 'uma hora|:count horas',
+ 'h' => ':counth',
+ 'minute' => ':count minuto|:count minutos',
+ 'a_minute' => 'um minuto|:count minutos',
+ 'min' => ':countmin',
+ 'second' => ':count segundo|:count segundos',
+ 'a_second' => 'alguns segundos|:count segundos',
+ 's' => ':counts',
+ 'millisecond' => ':count milissegundo|:count milissegundos',
+ 'a_millisecond' => 'um milissegundo|:count milissegundos',
+ 'ms' => ':countms',
+ 'microsecond' => ':count microssegundo|:count microssegundos',
+ 'a_microsecond' => 'um microssegundo|:count microssegundos',
+ 'µs' => ':countµs',
+ 'ago' => 'há :time',
+ 'from_now' => 'em :time',
+ 'after' => ':time depois',
+ 'before' => ':time antes',
+ 'diff_now' => 'agora',
+ 'diff_today' => 'Hoje',
+ 'diff_today_regexp' => 'Hoje(?:\\s+às)?',
+ 'diff_yesterday' => 'ontem',
+ 'diff_yesterday_regexp' => 'Ontem(?:\\s+às)?',
+ 'diff_tomorrow' => 'amanhã',
+ 'diff_tomorrow_regexp' => 'Amanhã(?:\\s+às)?',
+ 'diff_before_yesterday' => 'anteontem',
+ 'diff_after_tomorrow' => 'depois de amanhã',
+ 'period_recurrences' => 'uma vez|:count vezes',
+ 'period_interval' => 'cada :interval',
+ 'period_start_date' => 'de :date',
+ 'period_end_date' => 'até :date',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D [de] MMMM [de] YYYY',
+ 'LLL' => 'D [de] MMMM [de] YYYY HH:mm',
+ 'LLLL' => 'dddd, D [de] MMMM [de] YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Hoje às] LT',
+ 'nextDay' => '[Amanhã às] LT',
+ 'nextWeek' => 'dddd [às] LT',
+ 'lastDay' => '[Ontem às] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ case 6:
+ return '[Último] dddd [às] LT';
+ default:
+ return '[Última] dddd [às] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numberº',
+ 'months' => ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
+ 'months_short' => ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'],
+ 'weekdays' => ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
+ 'weekdays_short' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
+ 'weekdays_min' => ['Do', '2ª', '3ª', '4ª', '5ª', '6ª', 'Sá'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' e '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_AO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_AO.php
new file mode 100644
index 0000000..3d13bca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_AO.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/pt.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php
new file mode 100644
index 0000000..e917c5c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Cassiano Montanari
+ * - Eduardo Dalla Vecchia
+ * - David Rodrigues
+ * - Matt Pope
+ * - François B
+ * - Prodis
+ * - Marlon Maxwel
+ * - JD Isaacks
+ * - Raphael Amorim
+ * - Rafael Raupp
+ * - felipeleite1
+ * - swalker
+ * - Lucas Macedo
+ * - Paulo Freitas
+ * - Sebastian Thierer
+ */
+return array_replace_recursive(require __DIR__.'/pt.php', [
+ 'period_recurrences' => 'uma|:count vez',
+ 'period_interval' => 'toda :interval',
+ 'formats' => [
+ 'LLL' => 'D [de] MMMM [de] YYYY [às] HH:mm',
+ 'LLLL' => 'dddd, D [de] MMMM [de] YYYY [às] HH:mm',
+ ],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_CH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_CH.php
new file mode 100644
index 0000000..3d13bca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_CH.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/pt.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_CV.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_CV.php
new file mode 100644
index 0000000..3d13bca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_CV.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/pt.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_GQ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_GQ.php
new file mode 100644
index 0000000..3d13bca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_GQ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/pt.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_GW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_GW.php
new file mode 100644
index 0000000..3d13bca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_GW.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/pt.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_LU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_LU.php
new file mode 100644
index 0000000..3d13bca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_LU.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/pt.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_MO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_MO.php
new file mode 100644
index 0000000..331fa5c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_MO.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/pt.php', [
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'LLL' => 'D [de] MMMM [de] YYYY, h:mm a',
+ 'LLLL' => 'dddd, D [de] MMMM [de] YYYY, h:mm a',
+ ],
+ 'first_day_of_week' => 0,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_MZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_MZ.php
new file mode 100644
index 0000000..93bac23
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_MZ.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/pt.php', [
+ 'first_day_of_week' => 0,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_PT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_PT.php
new file mode 100644
index 0000000..2a76fc1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_PT.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RAP bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/pt.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
+ 'months_short' => ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'],
+ 'weekdays' => ['domingo', 'segunda', 'terça', 'quarta', 'quinta', 'sexta', 'sábado'],
+ 'weekdays_short' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
+ 'weekdays_min' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_ST.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_ST.php
new file mode 100644
index 0000000..3d13bca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_ST.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/pt.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_TL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_TL.php
new file mode 100644
index 0000000..3d13bca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pt_TL.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/pt.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/qu.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/qu.php
new file mode 100644
index 0000000..5f3a392
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/qu.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/es_UY.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM, YYYY HH:mm',
+ ],
+ 'first_day_of_week' => 0,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/qu_BO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/qu_BO.php
new file mode 100644
index 0000000..91635d5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/qu_BO.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/qu.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/qu_EC.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/qu_EC.php
new file mode 100644
index 0000000..91635d5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/qu_EC.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/qu.php', [
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/quz.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/quz.php
new file mode 100644
index 0000000..1640c02
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/quz.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/quz_PE.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/quz_PE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/quz_PE.php
new file mode 100644
index 0000000..d322918
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/quz_PE.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['iniru', 'phiwriru', 'marsu', 'awril', 'mayu', 'huniyu', 'huliyu', 'agustu', 'siptiyimri', 'uktuwri', 'nuwiyimri', 'tisiyimri'],
+ 'months_short' => ['ini', 'phi', 'mar', 'awr', 'may', 'hun', 'hul', 'agu', 'sip', 'ukt', 'nuw', 'tis'],
+ 'weekdays' => ['tuminku', 'lunis', 'martis', 'miyirkulis', 'juywis', 'wiyirnis', 'sawatu'],
+ 'weekdays_short' => ['tum', 'lun', 'mar', 'miy', 'juy', 'wiy', 'saw'],
+ 'weekdays_min' => ['tum', 'lun', 'mar', 'miy', 'juy', 'wiy', 'saw'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'minute' => ':count uchuy', // less reliable
+ 'min' => ':count uchuy', // less reliable
+ 'a_minute' => ':count uchuy', // less reliable
+
+ 'year' => ':count wata',
+ 'y' => ':count wata',
+ 'a_year' => ':count wata',
+
+ 'month' => ':count killa',
+ 'm' => ':count killa',
+ 'a_month' => ':count killa',
+
+ 'week' => ':count simana',
+ 'w' => ':count simana',
+ 'a_week' => ':count simana',
+
+ 'day' => ':count pʼunchaw',
+ 'd' => ':count pʼunchaw',
+ 'a_day' => ':count pʼunchaw',
+
+ 'hour' => ':count ura',
+ 'h' => ':count ura',
+ 'a_hour' => ':count ura',
+
+ 'second' => ':count iskay ñiqin',
+ 's' => ':count iskay ñiqin',
+ 'a_second' => ':count iskay ñiqin',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/raj.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/raj.php
new file mode 100644
index 0000000..26138c9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/raj.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/raj_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/raj_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/raj_IN.php
new file mode 100644
index 0000000..7b4589c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/raj_IN.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - meghrajsuthar03@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर'],
+ 'months_short' => ['जन', 'फर', 'मार्च', 'अप्रै', 'मई', 'जून', 'जुल', 'अग', 'सित', 'अक्टू', 'नव', 'दिस'],
+ 'weekdays' => ['रविवार', 'सोमवार', 'मंगल्लवार', 'बुधवार', 'बृहस्पतिवार', 'शुक्रवार', 'शनिवार'],
+ 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
+ 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
+
+ 'year' => ':count आंहू', // less reliable
+ 'y' => ':count आंहू', // less reliable
+ 'a_year' => ':count आंहू', // less reliable
+
+ 'month' => ':count सूरज', // less reliable
+ 'm' => ':count सूरज', // less reliable
+ 'a_month' => ':count सूरज', // less reliable
+
+ 'week' => ':count निवाज', // less reliable
+ 'w' => ':count निवाज', // less reliable
+ 'a_week' => ':count निवाज', // less reliable
+
+ 'day' => ':count अेक', // less reliable
+ 'd' => ':count अेक', // less reliable
+ 'a_day' => ':count अेक', // less reliable
+
+ 'hour' => ':count दुनियांण', // less reliable
+ 'h' => ':count दुनियांण', // less reliable
+ 'a_hour' => ':count दुनियांण', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rm.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rm.php
new file mode 100644
index 0000000..1843f45
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rm.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - tjku
+ * - Max Melentiev
+ * - Juanito Fatas
+ * - Tsutomu Kuroda
+ * - Akira Matsuda
+ * - Christopher Dell
+ * - Enrique Vidal
+ * - Simone Carletti
+ * - Aaron Patterson
+ * - Nicolás Hock Isaza
+ * - sebastian de castelberg
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'Do MMMM YYYY',
+ 'LLL' => 'Do MMMM, HH:mm [Uhr]',
+ 'LLLL' => 'dddd, Do MMMM YYYY, HH:mm [Uhr]',
+ ],
+ 'year' => ':count onn|:count onns',
+ 'month' => ':count mais',
+ 'week' => ':count emna|:count emnas',
+ 'day' => ':count di|:count dis',
+ 'hour' => ':count oura|:count ouras',
+ 'minute' => ':count minuta|:count minutas',
+ 'second' => ':count secunda|:count secundas',
+ 'weekdays' => ['dumengia', 'glindesdi', 'mardi', 'mesemna', 'gievgia', 'venderdi', 'sonda'],
+ 'weekdays_short' => ['du', 'gli', 'ma', 'me', 'gie', 've', 'so'],
+ 'weekdays_min' => ['du', 'gli', 'ma', 'me', 'gie', 've', 'so'],
+ 'months' => ['schaner', 'favrer', 'mars', 'avrigl', 'matg', 'zercladur', 'fanadur', 'avust', 'settember', 'october', 'november', 'december'],
+ 'months_short' => ['schan', 'favr', 'mars', 'avr', 'matg', 'zercl', 'fan', 'avust', 'sett', 'oct', 'nov', 'dec'],
+ 'meridiem' => ['avantmezdi', 'suentermezdi'],
+ 'list' => [', ', ' e '],
+ 'first_day_of_week' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rn.php
new file mode 100644
index 0000000..637d4e5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rn.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Z.MU.', 'Z.MW.'],
+ 'weekdays' => ['Ku w’indwi', 'Ku wa mbere', 'Ku wa kabiri', 'Ku wa gatatu', 'Ku wa kane', 'Ku wa gatanu', 'Ku wa gatandatu'],
+ 'weekdays_short' => ['cu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.', 'gnd.'],
+ 'weekdays_min' => ['cu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.', 'gnd.'],
+ 'months' => ['Nzero', 'Ruhuhuma', 'Ntwarante', 'Ndamukiza', 'Rusama', 'Ruheshi', 'Mukakaro', 'Nyandagaro', 'Nyakanga', 'Gitugutu', 'Munyonyo', 'Kigarama'],
+ 'months_short' => ['Mut.', 'Gas.', 'Wer.', 'Mat.', 'Gic.', 'Kam.', 'Nya.', 'Kan.', 'Nze.', 'Ukw.', 'Ugu.', 'Uku.'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => 'imyaka :count',
+ 'y' => 'imyaka :count',
+ 'a_year' => 'imyaka :count',
+
+ 'month' => 'amezi :count',
+ 'm' => 'amezi :count',
+ 'a_month' => 'amezi :count',
+
+ 'week' => 'indwi :count',
+ 'w' => 'indwi :count',
+ 'a_week' => 'indwi :count',
+
+ 'day' => 'imisi :count',
+ 'd' => 'imisi :count',
+ 'a_day' => 'imisi :count',
+
+ 'hour' => 'amasaha :count',
+ 'h' => 'amasaha :count',
+ 'a_hour' => 'amasaha :count',
+
+ 'minute' => 'iminuta :count',
+ 'min' => 'iminuta :count',
+ 'a_minute' => 'iminuta :count',
+
+ 'second' => 'inguvu :count', // less reliable
+ 's' => 'inguvu :count', // less reliable
+ 'a_second' => 'inguvu :count', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ro.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ro.php
new file mode 100644
index 0000000..868a327
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ro.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - JD Isaacks
+ * - Cătălin Georgescu
+ * - Valentin Ivaşcu (oriceon)
+ */
+return [
+ 'year' => ':count an|:count ani|:count ani',
+ 'a_year' => 'un an|:count ani|:count ani',
+ 'y' => ':count a.',
+ 'month' => ':count lună|:count luni|:count luni',
+ 'a_month' => 'o lună|:count luni|:count luni',
+ 'm' => ':count l.',
+ 'week' => ':count săptămână|:count săptămâni|:count săptămâni',
+ 'a_week' => 'o săptămână|:count săptămâni|:count săptămâni',
+ 'w' => ':count săp.',
+ 'day' => ':count zi|:count zile|:count zile',
+ 'a_day' => 'o zi|:count zile|:count zile',
+ 'd' => ':count z.',
+ 'hour' => ':count oră|:count ore|:count ore',
+ 'a_hour' => 'o oră|:count ore|:count ore',
+ 'h' => ':count o.',
+ 'minute' => ':count minut|:count minute|:count minute',
+ 'a_minute' => 'un minut|:count minute|:count minute',
+ 'min' => ':count m.',
+ 'second' => ':count secundă|:count secunde|:count secunde',
+ 'a_second' => 'câteva secunde|:count secunde|:count secunde',
+ 's' => ':count sec.',
+ 'ago' => ':time în urmă',
+ 'from_now' => 'peste :time',
+ 'after' => 'peste :time',
+ 'before' => 'acum :time',
+ 'diff_now' => 'acum',
+ 'diff_today' => 'azi',
+ 'diff_today_regexp' => 'azi(?:\\s+la)?',
+ 'diff_yesterday' => 'ieri',
+ 'diff_yesterday_regexp' => 'ieri(?:\\s+la)?',
+ 'diff_tomorrow' => 'mâine',
+ 'diff_tomorrow_regexp' => 'mâine(?:\\s+la)?',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY H:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[azi la] LT',
+ 'nextDay' => '[mâine la] LT',
+ 'nextWeek' => 'dddd [la] LT',
+ 'lastDay' => '[ieri la] LT',
+ 'lastWeek' => '[fosta] dddd [la] LT',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['ianuarie', 'februarie', 'martie', 'aprilie', 'mai', 'iunie', 'iulie', 'august', 'septembrie', 'octombrie', 'noiembrie', 'decembrie'],
+ 'months_short' => ['ian.', 'feb.', 'mar.', 'apr.', 'mai', 'iun.', 'iul.', 'aug.', 'sept.', 'oct.', 'nov.', 'dec.'],
+ 'weekdays' => ['duminică', 'luni', 'marți', 'miercuri', 'joi', 'vineri', 'sâmbătă'],
+ 'weekdays_short' => ['dum', 'lun', 'mar', 'mie', 'joi', 'vin', 'sâm'],
+ 'weekdays_min' => ['du', 'lu', 'ma', 'mi', 'jo', 'vi', 'sâ'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' și '],
+ 'meridiem' => ['a.m.', 'p.m.'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ro_MD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ro_MD.php
new file mode 100644
index 0000000..0ba6f68
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ro_MD.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ro.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY, HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ro_RO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ro_RO.php
new file mode 100644
index 0000000..dd7c8f0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ro_RO.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ro.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rof.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rof.php
new file mode 100644
index 0000000..80ab454
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rof.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['kang’ama', 'kingoto'],
+ 'weekdays' => ['Ijumapili', 'Ijumatatu', 'Ijumanne', 'Ijumatano', 'Alhamisi', 'Ijumaa', 'Ijumamosi'],
+ 'weekdays_short' => ['Ijp', 'Ijt', 'Ijn', 'Ijtn', 'Alh', 'Iju', 'Ijm'],
+ 'weekdays_min' => ['Ijp', 'Ijt', 'Ijn', 'Ijtn', 'Alh', 'Iju', 'Ijm'],
+ 'months' => ['Mweri wa kwanza', 'Mweri wa kaili', 'Mweri wa katatu', 'Mweri wa kaana', 'Mweri wa tanu', 'Mweri wa sita', 'Mweri wa saba', 'Mweri wa nane', 'Mweri wa tisa', 'Mweri wa ikumi', 'Mweri wa ikumi na moja', 'Mweri wa ikumi na mbili'],
+ 'months_short' => ['M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', 'M9', 'M10', 'M11', 'M12'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru.php
new file mode 100644
index 0000000..93e0e01
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru.php
@@ -0,0 +1,188 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Bari Badamshin
+ * - Jørn Ølmheim
+ * - François B
+ * - Tim Fish
+ * - Коренберг Марк (imac)
+ * - Serhan Apaydın
+ * - RomeroMsk
+ * - vsn4ik
+ * - JD Isaacks
+ * - Bari Badamshin
+ * - Jørn Ølmheim
+ * - François B
+ * - Коренберг Марк (imac)
+ * - Serhan Apaydın
+ * - RomeroMsk
+ * - vsn4ik
+ * - JD Isaacks
+ * - Fellzo
+ * - andrey-helldar
+ * - Pavel Skripkin (psxx)
+ * - AlexWalkerson
+ * - Vladislav UnsealedOne
+ * - dima-bzz
+ */
+$transformDiff = function ($input) {
+ return strtr($input, [
+ 'неделя' => 'неделю',
+ 'секунда' => 'секунду',
+ 'минута' => 'минуту',
+ ]);
+};
+
+return [
+ 'year' => ':count год|:count года|:count лет',
+ 'y' => ':count г.|:count г.|:count л.',
+ 'a_year' => '{1}год|:count год|:count года|:count лет',
+ 'month' => ':count месяц|:count месяца|:count месяцев',
+ 'm' => ':count мес.',
+ 'a_month' => '{1}месяц|:count месяц|:count месяца|:count месяцев',
+ 'week' => ':count неделя|:count недели|:count недель',
+ 'w' => ':count нед.',
+ 'a_week' => '{1}неделя|:count неделю|:count недели|:count недель',
+ 'day' => ':count день|:count дня|:count дней',
+ 'd' => ':count д.',
+ 'a_day' => '{1}день|:count день|:count дня|:count дней',
+ 'hour' => ':count час|:count часа|:count часов',
+ 'h' => ':count ч.',
+ 'a_hour' => '{1}час|:count час|:count часа|:count часов',
+ 'minute' => ':count минута|:count минуты|:count минут',
+ 'min' => ':count мин.',
+ 'a_minute' => '{1}минута|:count минута|:count минуты|:count минут',
+ 'second' => ':count секунда|:count секунды|:count секунд',
+ 's' => ':count сек.',
+ 'a_second' => '{1}несколько секунд|:count секунду|:count секунды|:count секунд',
+ 'ago' => function ($time) use ($transformDiff) {
+ return $transformDiff($time).' назад';
+ },
+ 'from_now' => function ($time) use ($transformDiff) {
+ return 'через '.$transformDiff($time);
+ },
+ 'after' => function ($time) use ($transformDiff) {
+ return $transformDiff($time).' после';
+ },
+ 'before' => function ($time) use ($transformDiff) {
+ return $transformDiff($time).' до';
+ },
+ 'diff_now' => 'только что',
+ 'diff_today' => 'Сегодня,',
+ 'diff_today_regexp' => 'Сегодня,?(?:\\s+в)?',
+ 'diff_yesterday' => 'вчера',
+ 'diff_yesterday_regexp' => 'Вчера,?(?:\\s+в)?',
+ 'diff_tomorrow' => 'завтра',
+ 'diff_tomorrow_regexp' => 'Завтра,?(?:\\s+в)?',
+ 'diff_before_yesterday' => 'позавчера',
+ 'diff_after_tomorrow' => 'послезавтра',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY г.',
+ 'LLL' => 'D MMMM YYYY г., H:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY г., H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Сегодня, в] LT',
+ 'nextDay' => '[Завтра, в] LT',
+ 'nextWeek' => function (\Carbon\CarbonInterface $current, \Carbon\CarbonInterface $other) {
+ if ($current->week !== $other->week) {
+ switch ($current->dayOfWeek) {
+ case 0:
+ return '[В следующее] dddd, [в] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[В следующий] dddd, [в] LT';
+ case 3:
+ case 5:
+ case 6:
+ return '[В следующую] dddd, [в] LT';
+ }
+ }
+
+ if ($current->dayOfWeek === 2) {
+ return '[Во] dddd, [в] LT';
+ }
+
+ return '[В] dddd, [в] LT';
+ },
+ 'lastDay' => '[Вчера, в] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $current, \Carbon\CarbonInterface $other) {
+ if ($current->week !== $other->week) {
+ switch ($current->dayOfWeek) {
+ case 0:
+ return '[В прошлое] dddd, [в] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[В прошлый] dddd, [в] LT';
+ case 3:
+ case 5:
+ case 6:
+ return '[В прошлую] dddd, [в] LT';
+ }
+ }
+
+ if ($current->dayOfWeek === 2) {
+ return '[Во] dddd, [в] LT';
+ }
+
+ return '[В] dddd, [в] LT';
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ case 'M':
+ case 'd':
+ case 'DDD':
+ return $number.'-й';
+ case 'D':
+ return $number.'-го';
+ case 'w':
+ case 'W':
+ return $number.'-я';
+ default:
+ return $number;
+ }
+ },
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'ночи';
+ }
+ if ($hour < 12) {
+ return 'утра';
+ }
+ if ($hour < 17) {
+ return 'дня';
+ }
+
+ return 'вечера';
+ },
+ 'months' => ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'],
+ 'months_standalone' => ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
+ 'months_short' => ['янв', 'фев', 'мар', 'апр', 'мая', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
+ 'months_short_standalone' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
+ 'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
+ 'weekdays' => ['воскресенье', 'понедельник', 'вторник', 'среду', 'четверг', 'пятницу', 'субботу'],
+ 'weekdays_standalone' => ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'],
+ 'weekdays_short' => ['вск', 'пнд', 'втр', 'срд', 'чтв', 'птн', 'сбт'],
+ 'weekdays_min' => ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
+ 'weekdays_regexp' => '/\[\s*(В|в)\s*((?:прошлую|следующую|эту)\s*)?\]\s*dddd/',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' и '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_BY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_BY.php
new file mode 100644
index 0000000..2c8d78f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_BY.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ru.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_KG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_KG.php
new file mode 100644
index 0000000..2c8d78f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_KG.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ru.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_KZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_KZ.php
new file mode 100644
index 0000000..2c8d78f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_KZ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ru.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_MD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_MD.php
new file mode 100644
index 0000000..2c8d78f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_MD.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ru.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_RU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_RU.php
new file mode 100644
index 0000000..2c8d78f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_RU.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ru.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_UA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_UA.php
new file mode 100644
index 0000000..db958d6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ru_UA.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - RFC 2319 bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ru.php', [
+ 'weekdays' => ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'],
+ 'weekdays_short' => ['вск', 'пнд', 'вто', 'срд', 'чтв', 'птн', 'суб'],
+ 'weekdays_min' => ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'су'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rw.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rw.php
new file mode 100644
index 0000000..bc4a347
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rw.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/rw_RW.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rw_RW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rw_RW.php
new file mode 100644
index 0000000..9b3e068
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rw_RW.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Rwanda Steve Murphy murf@e-tools.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['Mutarama', 'Gashyantare', 'Werurwe', 'Mata', 'Gicuransi', 'Kamena', 'Nyakanga', 'Kanama', 'Nzeli', 'Ukwakira', 'Ugushyingo', 'Ukuboza'],
+ 'months_short' => ['Mut', 'Gas', 'Wer', 'Mat', 'Gic', 'Kam', 'Nya', 'Kan', 'Nze', 'Ukw', 'Ugu', 'Uku'],
+ 'weekdays' => ['Ku cyumweru', 'Kuwa mbere', 'Kuwa kabiri', 'Kuwa gatatu', 'Kuwa kane', 'Kuwa gatanu', 'Kuwa gatandatu'],
+ 'weekdays_short' => ['Mwe', 'Mbe', 'Kab', 'Gtu', 'Kan', 'Gnu', 'Gnd'],
+ 'weekdays_min' => ['Mwe', 'Mbe', 'Kab', 'Gtu', 'Kan', 'Gnu', 'Gnd'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'second' => ':count vuna', // less reliable
+ 's' => ':count vuna', // less reliable
+ 'a_second' => ':count vuna', // less reliable
+
+ 'year' => 'aka :count',
+ 'y' => 'aka :count',
+ 'a_year' => 'aka :count',
+
+ 'month' => 'ezi :count',
+ 'm' => 'ezi :count',
+ 'a_month' => 'ezi :count',
+
+ 'week' => ':count icyumweru',
+ 'w' => ':count icyumweru',
+ 'a_week' => ':count icyumweru',
+
+ 'day' => ':count nsi',
+ 'd' => ':count nsi',
+ 'a_day' => ':count nsi',
+
+ 'hour' => 'saha :count',
+ 'h' => 'saha :count',
+ 'a_hour' => 'saha :count',
+
+ 'minute' => ':count -nzinya',
+ 'min' => ':count -nzinya',
+ 'a_minute' => ':count -nzinya',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rwk.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rwk.php
new file mode 100644
index 0000000..f8cc72c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/rwk.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['utuko', 'kyiukonyi'],
+ 'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
+ 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sa.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sa.php
new file mode 100644
index 0000000..1357c03
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sa.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/sa_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sa_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sa_IN.php
new file mode 100644
index 0000000..cfda9a6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sa_IN.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - The Debian project Christian Perrier bubulle@debian.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D-MM-YY',
+ ],
+ 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
+ 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
+ 'weekdays' => ['रविवासर:', 'सोमवासर:', 'मंगलवासर:', 'बुधवासर:', 'बृहस्पतिवासरः', 'शुक्रवासर', 'शनिवासर:'],
+ 'weekdays_short' => ['रविः', 'सोम:', 'मंगल:', 'बुध:', 'बृहस्पतिः', 'शुक्र', 'शनि:'],
+ 'weekdays_min' => ['रविः', 'सोम:', 'मंगल:', 'बुध:', 'बृहस्पतिः', 'शुक्र', 'शनि:'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
+
+ 'minute' => ':count होरा', // less reliable
+ 'min' => ':count होरा', // less reliable
+ 'a_minute' => ':count होरा', // less reliable
+
+ 'year' => ':count वर्ष',
+ 'y' => ':count वर्ष',
+ 'a_year' => ':count वर्ष',
+
+ 'month' => ':count मास',
+ 'm' => ':count मास',
+ 'a_month' => ':count मास',
+
+ 'week' => ':count सप्ताहः saptahaĥ',
+ 'w' => ':count सप्ताहः saptahaĥ',
+ 'a_week' => ':count सप्ताहः saptahaĥ',
+
+ 'day' => ':count दिन',
+ 'd' => ':count दिन',
+ 'a_day' => ':count दिन',
+
+ 'hour' => ':count घण्टा',
+ 'h' => ':count घण्टा',
+ 'a_hour' => ':count घण्टा',
+
+ 'second' => ':count द्वितीयः',
+ 's' => ':count द्वितीयः',
+ 'a_second' => ':count द्वितीयः',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sah.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sah.php
new file mode 100644
index 0000000..b828824
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sah.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/sah_RU.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sah_RU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sah_RU.php
new file mode 100644
index 0000000..94cc0cb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sah_RU.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Valery Timiriliyev Valery Timiriliyev timiriliyev@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/ru.php', [
+ 'formats' => [
+ 'L' => 'YYYY.MM.DD',
+ ],
+ 'months' => ['тохсунньу', 'олунньу', 'кулун тутар', 'муус устар', 'ыам ыйын', 'бэс ыйын', 'от ыйын', 'атырдьах ыйын', 'балаҕан ыйын', 'алтынньы', 'сэтинньи', 'ахсынньы'],
+ 'months_short' => ['тохс', 'олун', 'кул', 'муус', 'ыам', 'бэс', 'от', 'атыр', 'бал', 'алт', 'сэт', 'ахс'],
+ 'weekdays' => ['баскыһыанньа', 'бэнидиэнньик', 'оптуорунньук', 'сэрэдэ', 'чэппиэр', 'бээтинсэ', 'субуота'],
+ 'weekdays_short' => ['бс', 'бн', 'оп', 'ср', 'чп', 'бт', 'сб'],
+ 'weekdays_min' => ['бс', 'бн', 'оп', 'ср', 'чп', 'бт', 'сб'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/saq.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/saq.php
new file mode 100644
index 0000000..eebfac9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/saq.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Tesiran', 'Teipa'],
+ 'weekdays' => ['Mderot ee are', 'Mderot ee kuni', 'Mderot ee ong’wan', 'Mderot ee inet', 'Mderot ee ile', 'Mderot ee sapa', 'Mderot ee kwe'],
+ 'weekdays_short' => ['Are', 'Kun', 'Ong', 'Ine', 'Ile', 'Sap', 'Kwe'],
+ 'weekdays_min' => ['Are', 'Kun', 'Ong', 'Ine', 'Ile', 'Sap', 'Kwe'],
+ 'months' => ['Lapa le obo', 'Lapa le waare', 'Lapa le okuni', 'Lapa le ong’wan', 'Lapa le imet', 'Lapa le ile', 'Lapa le sapa', 'Lapa le isiet', 'Lapa le saal', 'Lapa le tomon', 'Lapa le tomon obo', 'Lapa le tomon waare'],
+ 'months_short' => ['Obo', 'Waa', 'Oku', 'Ong', 'Ime', 'Ile', 'Sap', 'Isi', 'Saa', 'Tom', 'Tob', 'Tow'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sat.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sat.php
new file mode 100644
index 0000000..c9914c6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sat.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/sat_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sat_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sat_IN.php
new file mode 100644
index 0000000..632b1af
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sat_IN.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Red Hat Pune libc-alpha@sourceware.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रेल', 'मई', 'जुन', 'जुलाई', 'अगस्त', 'सितम्बर', 'अखथबर', 'नवम्बर', 'दिसम्बर'],
+ 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रेल', 'मई', 'जुन', 'जुलाई', 'अगस्त', 'सितम्बर', 'अखथबर', 'नवम्बर', 'दिसम्बर'],
+ 'weekdays' => ['सिंगेमाँहाँ', 'ओतेमाँहाँ', 'बालेमाँहाँ', 'सागुनमाँहाँ', 'सारदीमाँहाँ', 'जारुममाँहाँ', 'ञुहुममाँहाँ'],
+ 'weekdays_short' => ['सिंगे', 'ओते', 'बाले', 'सागुन', 'सारदी', 'जारुम', 'ञुहुम'],
+ 'weekdays_min' => ['सिंगे', 'ओते', 'बाले', 'सागुन', 'सारदी', 'जारुम', 'ञुहुम'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'month' => ':count ńindạ cando', // less reliable
+ 'm' => ':count ńindạ cando', // less reliable
+ 'a_month' => ':count ńindạ cando', // less reliable
+
+ 'week' => ':count mãhã', // less reliable
+ 'w' => ':count mãhã', // less reliable
+ 'a_week' => ':count mãhã', // less reliable
+
+ 'hour' => ':count ᱥᱳᱱᱚ', // less reliable
+ 'h' => ':count ᱥᱳᱱᱚ', // less reliable
+ 'a_hour' => ':count ᱥᱳᱱᱚ', // less reliable
+
+ 'minute' => ':count ᱯᱤᱞᱪᱩ', // less reliable
+ 'min' => ':count ᱯᱤᱞᱪᱩ', // less reliable
+ 'a_minute' => ':count ᱯᱤᱞᱪᱩ', // less reliable
+
+ 'second' => ':count ar', // less reliable
+ 's' => ':count ar', // less reliable
+ 'a_second' => ':count ar', // less reliable
+
+ 'year' => ':count ne̲s',
+ 'y' => ':count ne̲s',
+ 'a_year' => ':count ne̲s',
+
+ 'day' => ':count ᱫᱤᱱ',
+ 'd' => ':count ᱫᱤᱱ',
+ 'a_day' => ':count ᱫᱤᱱ',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sbp.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sbp.php
new file mode 100644
index 0000000..9b73783
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sbp.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Lwamilawu', 'Pashamihe'],
+ 'weekdays' => ['Mulungu', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alahamisi', 'Ijumaa', 'Jumamosi'],
+ 'weekdays_short' => ['Mul', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'weekdays_min' => ['Mul', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'months' => ['Mupalangulwa', 'Mwitope', 'Mushende', 'Munyi', 'Mushende Magali', 'Mujimbi', 'Mushipepo', 'Mupuguto', 'Munyense', 'Mokhu', 'Musongandembwe', 'Muhaano'],
+ 'months_short' => ['Mup', 'Mwi', 'Msh', 'Mun', 'Mag', 'Muj', 'Msp', 'Mpg', 'Mye', 'Mok', 'Mus', 'Muh'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sc.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sc.php
new file mode 100644
index 0000000..7178cf4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sc.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/sc_IT.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sc_IT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sc_IT.php
new file mode 100644
index 0000000..5d1e4ce
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sc_IT.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Sardinian Translators Team Massimeddu Cireddu massimeddu@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD. MM. YY',
+ ],
+ 'months' => ['Ghennàrgiu', 'Freàrgiu', 'Martzu', 'Abrile', 'Maju', 'Làmpadas', 'Argiolas//Trìulas', 'Austu', 'Cabudanni', 'Santugaine//Ladàmine', 'Onniasantu//Santandria', 'Nadale//Idas'],
+ 'months_short' => ['Ghe', 'Fre', 'Mar', 'Abr', 'Maj', 'Làm', 'Arg', 'Aus', 'Cab', 'Lad', 'Onn', 'Nad'],
+ 'weekdays' => ['Domìnigu', 'Lunis', 'Martis', 'Mèrcuris', 'Giòbia', 'Chenàbura', 'Sàbadu'],
+ 'weekdays_short' => ['Dom', 'Lun', 'Mar', 'Mèr', 'Giò', 'Che', 'Sàb'],
+ 'weekdays_min' => ['Dom', 'Lun', 'Mar', 'Mèr', 'Giò', 'Che', 'Sàb'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'minute' => ':count mementu', // less reliable
+ 'min' => ':count mementu', // less reliable
+ 'a_minute' => ':count mementu', // less reliable
+
+ 'year' => ':count annu',
+ 'y' => ':count annu',
+ 'a_year' => ':count annu',
+
+ 'month' => ':count mese',
+ 'm' => ':count mese',
+ 'a_month' => ':count mese',
+
+ 'week' => ':count chida',
+ 'w' => ':count chida',
+ 'a_week' => ':count chida',
+
+ 'day' => ':count dí',
+ 'd' => ':count dí',
+ 'a_day' => ':count dí',
+
+ 'hour' => ':count ora',
+ 'h' => ':count ora',
+ 'a_hour' => ':count ora',
+
+ 'second' => ':count secundu',
+ 's' => ':count secundu',
+ 'a_second' => ':count secundu',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sd.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sd.php
new file mode 100644
index 0000000..ad8c000
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sd.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+$months = [
+ 'جنوري',
+ 'فيبروري',
+ 'مارچ',
+ 'اپريل',
+ 'مئي',
+ 'جون',
+ 'جولاءِ',
+ 'آگسٽ',
+ 'سيپٽمبر',
+ 'آڪٽوبر',
+ 'نومبر',
+ 'ڊسمبر',
+];
+
+$weekdays = [
+ 'آچر',
+ 'سومر',
+ 'اڱارو',
+ 'اربع',
+ 'خميس',
+ 'جمع',
+ 'ڇنڇر',
+];
+
+/*
+ * Authors:
+ * - Narain Sagar
+ * - Sawood Alam
+ * - Narain Sagar
+ */
+return [
+ 'year' => '{1}'.'هڪ سال'.'|:count '.'سال',
+ 'month' => '{1}'.'هڪ مهينو'.'|:count '.'مهينا',
+ 'week' => '{1}'.'ھڪ ھفتو'.'|:count '.'هفتا',
+ 'day' => '{1}'.'هڪ ڏينهن'.'|:count '.'ڏينهن',
+ 'hour' => '{1}'.'هڪ ڪلاڪ'.'|:count '.'ڪلاڪ',
+ 'minute' => '{1}'.'هڪ منٽ'.'|:count '.'منٽ',
+ 'second' => '{1}'.'چند سيڪنڊ'.'|:count '.'سيڪنڊ',
+ 'ago' => ':time اڳ',
+ 'from_now' => ':time پوء',
+ 'diff_yesterday' => 'ڪالهه',
+ 'diff_today' => 'اڄ',
+ 'diff_tomorrow' => 'سڀاڻي',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd، D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[اڄ] LT',
+ 'nextDay' => '[سڀاڻي] LT',
+ 'nextWeek' => 'dddd [اڳين هفتي تي] LT',
+ 'lastDay' => '[ڪالهه] LT',
+ 'lastWeek' => '[گزريل هفتي] dddd [تي] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['صبح', 'شام'],
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => $weekdays,
+ 'weekdays_short' => $weekdays,
+ 'weekdays_min' => $weekdays,
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => ['، ', ' ۽ '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sd_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sd_IN.php
new file mode 100644
index 0000000..de1dad0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sd_IN.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Red Hat, Pune bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/sd.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['جنوري', 'فبروري', 'مارچ', 'اپريل', 'مي', 'جون', 'جولاءِ', 'آگسٽ', 'سيپٽيمبر', 'آڪٽوبر', 'نومبر', 'ڊسمبر'],
+ 'months_short' => ['جنوري', 'فبروري', 'مارچ', 'اپريل', 'مي', 'جون', 'جولاءِ', 'آگسٽ', 'سيپٽيمبر', 'آڪٽوبر', 'نومبر', 'ڊسمبر'],
+ 'weekdays' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'],
+ 'weekdays_short' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'],
+ 'weekdays_min' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sd_IN@devanagari.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sd_IN@devanagari.php
new file mode 100644
index 0000000..061fcc1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sd_IN@devanagari.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Red Hat, Pune bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/sd.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['जनवरी', 'फबरवरी', 'मार्चि', 'अप्रेल', 'मे', 'जूनि', 'जूलाइ', 'आगस्टु', 'सेप्टेंबरू', 'आक्टूबरू', 'नवंबरू', 'ॾिसंबरू'],
+ 'months_short' => ['जनवरी', 'फबरवरी', 'मार्चि', 'अप्रेल', 'मे', 'जूनि', 'जूलाइ', 'आगस्टु', 'सेप्टेंबरू', 'आक्टूबरू', 'नवंबरू', 'ॾिसंबरू'],
+ 'weekdays' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'],
+ 'weekdays_short' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'],
+ 'weekdays_min' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['म.पू.', 'म.नं.'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se.php
new file mode 100644
index 0000000..7c4b92a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Karamell
+ */
+return [
+ 'year' => '{1}:count jahki|:count jagit',
+ 'a_year' => '{1}okta jahki|:count jagit',
+ 'y' => ':count j.',
+ 'month' => '{1}:count mánnu|:count mánut',
+ 'a_month' => '{1}okta mánnu|:count mánut',
+ 'm' => ':count mán.',
+ 'week' => '{1}:count vahkku|:count vahkku',
+ 'a_week' => '{1}okta vahkku|:count vahkku',
+ 'w' => ':count v.',
+ 'day' => '{1}:count beaivi|:count beaivvit',
+ 'a_day' => '{1}okta beaivi|:count beaivvit',
+ 'd' => ':count b.',
+ 'hour' => '{1}:count diimmu|:count diimmut',
+ 'a_hour' => '{1}okta diimmu|:count diimmut',
+ 'h' => ':count d.',
+ 'minute' => '{1}:count minuhta|:count minuhtat',
+ 'a_minute' => '{1}okta minuhta|:count minuhtat',
+ 'min' => ':count min.',
+ 'second' => '{1}:count sekunddat|:count sekunddat',
+ 'a_second' => '{1}moadde sekunddat|:count sekunddat',
+ 's' => ':count s.',
+ 'ago' => 'maŋit :time',
+ 'from_now' => ':time geažes',
+ 'diff_yesterday' => 'ikte',
+ 'diff_yesterday_regexp' => 'ikte(?:\\s+ti)?',
+ 'diff_today' => 'otne',
+ 'diff_today_regexp' => 'otne(?:\\s+ti)?',
+ 'diff_tomorrow' => 'ihttin',
+ 'diff_tomorrow_regexp' => 'ihttin(?:\\s+ti)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'MMMM D. [b.] YYYY',
+ 'LLL' => 'MMMM D. [b.] YYYY [ti.] HH:mm',
+ 'LLLL' => 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[otne ti] LT',
+ 'nextDay' => '[ihttin ti] LT',
+ 'nextWeek' => 'dddd [ti] LT',
+ 'lastDay' => '[ikte ti] LT',
+ 'lastWeek' => '[ovddit] dddd [ti] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu', 'cuoŋománnu', 'miessemánnu', 'geassemánnu', 'suoidnemánnu', 'borgemánnu', 'čakčamánnu', 'golggotmánnu', 'skábmamánnu', 'juovlamánnu'],
+ 'months_short' => ['ođđj', 'guov', 'njuk', 'cuo', 'mies', 'geas', 'suoi', 'borg', 'čakč', 'golg', 'skáb', 'juov'],
+ 'weekdays' => ['sotnabeaivi', 'vuossárga', 'maŋŋebárga', 'gaskavahkku', 'duorastat', 'bearjadat', 'lávvardat'],
+ 'weekdays_short' => ['sotn', 'vuos', 'maŋ', 'gask', 'duor', 'bear', 'láv'],
+ 'weekdays_min' => ['s', 'v', 'm', 'g', 'd', 'b', 'L'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' ja '],
+ 'meridiem' => ['i.b.', 'e.b.'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se_FI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se_FI.php
new file mode 100644
index 0000000..b2b967e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se_FI.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/se.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'months' => ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu', 'cuoŋománnu', 'miessemánnu', 'geassemánnu', 'suoidnemánnu', 'borgemánnu', 'čakčamánnu', 'golggotmánnu', 'skábmamánnu', 'juovlamánnu'],
+ 'months_short' => ['ođđj', 'guov', 'njuk', 'cuoŋ', 'mies', 'geas', 'suoi', 'borg', 'čakč', 'golg', 'skáb', 'juov'],
+ 'weekdays' => ['sotnabeaivi', 'mánnodat', 'disdat', 'gaskavahkku', 'duorastat', 'bearjadat', 'lávvordat'],
+ 'weekdays_short' => ['so', 'má', 'di', 'ga', 'du', 'be', 'lá'],
+ 'weekdays_min' => ['so', 'má', 'di', 'ga', 'du', 'be', 'lá'],
+ 'meridiem' => ['i', 'e'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se_NO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se_NO.php
new file mode 100644
index 0000000..83bbf78
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se_NO.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/se.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se_SE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se_SE.php
new file mode 100644
index 0000000..83bbf78
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/se_SE.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/se.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/seh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/seh.php
new file mode 100644
index 0000000..3ad889a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/seh.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'weekdays' => ['Dimingu', 'Chiposi', 'Chipiri', 'Chitatu', 'Chinai', 'Chishanu', 'Sabudu'],
+ 'weekdays_short' => ['Dim', 'Pos', 'Pir', 'Tat', 'Nai', 'Sha', 'Sab'],
+ 'weekdays_min' => ['Dim', 'Pos', 'Pir', 'Tat', 'Nai', 'Sha', 'Sab'],
+ 'months' => ['Janeiro', 'Fevreiro', 'Marco', 'Abril', 'Maio', 'Junho', 'Julho', 'Augusto', 'Setembro', 'Otubro', 'Novembro', 'Decembro'],
+ 'months_short' => ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Aug', 'Set', 'Otu', 'Nov', 'Dec'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'd [de] MMM [de] YYYY',
+ 'LLL' => 'd [de] MMMM [de] YYYY HH:mm',
+ 'LLLL' => 'dddd, d [de] MMMM [de] YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ses.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ses.php
new file mode 100644
index 0000000..9355184
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ses.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Adduha', 'Aluula'],
+ 'weekdays' => ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamiisa', 'Alzuma', 'Asibti'],
+ 'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
+ 'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
+ 'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
+ 'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+
+ 'month' => ':count alaada', // less reliable
+ 'm' => ':count alaada', // less reliable
+ 'a_month' => ':count alaada', // less reliable
+
+ 'hour' => ':count ɲaajin', // less reliable
+ 'h' => ':count ɲaajin', // less reliable
+ 'a_hour' => ':count ɲaajin', // less reliable
+
+ 'minute' => ':count zarbu', // less reliable
+ 'min' => ':count zarbu', // less reliable
+ 'a_minute' => ':count zarbu', // less reliable
+
+ 'year' => ':count jiiri',
+ 'y' => ':count jiiri',
+ 'a_year' => ':count jiiri',
+
+ 'week' => ':count jirbiiyye',
+ 'w' => ':count jirbiiyye',
+ 'a_week' => ':count jirbiiyye',
+
+ 'day' => ':count zaari',
+ 'd' => ':count zaari',
+ 'a_day' => ':count zaari',
+
+ 'second' => ':count ihinkante',
+ 's' => ':count ihinkante',
+ 'a_second' => ':count ihinkante',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sg.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sg.php
new file mode 100644
index 0000000..7f8e9da
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sg.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['ND', 'LK'],
+ 'weekdays' => ['Bikua-ôko', 'Bïkua-ûse', 'Bïkua-ptâ', 'Bïkua-usïö', 'Bïkua-okü', 'Lâpôsö', 'Lâyenga'],
+ 'weekdays_short' => ['Bk1', 'Bk2', 'Bk3', 'Bk4', 'Bk5', 'Lâp', 'Lây'],
+ 'weekdays_min' => ['Bk1', 'Bk2', 'Bk3', 'Bk4', 'Bk5', 'Lâp', 'Lây'],
+ 'months' => ['Nyenye', 'Fulundïgi', 'Mbängü', 'Ngubùe', 'Bêläwü', 'Föndo', 'Lengua', 'Kükürü', 'Mvuka', 'Ngberere', 'Nabändüru', 'Kakauka'],
+ 'months_short' => ['Nye', 'Ful', 'Mbä', 'Ngu', 'Bêl', 'Fön', 'Len', 'Kük', 'Mvu', 'Ngb', 'Nab', 'Kak'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => ':count dā', // less reliable
+ 'y' => ':count dā', // less reliable
+ 'a_year' => ':count dā', // less reliable
+
+ 'week' => ':count bïkua-okü', // less reliable
+ 'w' => ':count bïkua-okü', // less reliable
+ 'a_week' => ':count bïkua-okü', // less reliable
+
+ 'day' => ':count ziggawâ', // less reliable
+ 'd' => ':count ziggawâ', // less reliable
+ 'a_day' => ':count ziggawâ', // less reliable
+
+ 'hour' => ':count yângâködörö', // less reliable
+ 'h' => ':count yângâködörö', // less reliable
+ 'a_hour' => ':count yângâködörö', // less reliable
+
+ 'second' => ':count bïkua-ôko', // less reliable
+ 's' => ':count bïkua-ôko', // less reliable
+ 'a_second' => ':count bïkua-ôko', // less reliable
+
+ 'month' => ':count Nze tî ngu',
+ 'm' => ':count Nze tî ngu',
+ 'a_month' => ':count Nze tî ngu',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sgs.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sgs.php
new file mode 100644
index 0000000..864b989
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sgs.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/sgs_LT.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sgs_LT.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sgs_LT.php
new file mode 100644
index 0000000..aa9e942
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sgs_LT.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Arnas Udovičius bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY.MM.DD',
+ ],
+ 'months' => ['sausė', 'vasarė', 'kuova', 'balondė', 'gegožės', 'bėrželė', 'lëpas', 'rogpjūtė', 'siejės', 'spalė', 'lapkrėstė', 'grůdė'],
+ 'months_short' => ['Sau', 'Vas', 'Kuo', 'Bal', 'Geg', 'Bėr', 'Lëp', 'Rgp', 'Sie', 'Spa', 'Lap', 'Grd'],
+ 'weekdays' => ['nedielės dëna', 'panedielis', 'oterninks', 'sereda', 'četvergs', 'petnīčė', 'sobata'],
+ 'weekdays_short' => ['Nd', 'Pn', 'Ot', 'Sr', 'Čt', 'Pt', 'Sb'],
+ 'weekdays_min' => ['Nd', 'Pn', 'Ot', 'Sr', 'Čt', 'Pt', 'Sb'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'minute' => ':count mažos', // less reliable
+ 'min' => ':count mažos', // less reliable
+ 'a_minute' => ':count mažos', // less reliable
+
+ 'year' => ':count metā',
+ 'y' => ':count metā',
+ 'a_year' => ':count metā',
+
+ 'month' => ':count mienou',
+ 'm' => ':count mienou',
+ 'a_month' => ':count mienou',
+
+ 'week' => ':count nedielė',
+ 'w' => ':count nedielė',
+ 'a_week' => ':count nedielė',
+
+ 'day' => ':count dīna',
+ 'd' => ':count dīna',
+ 'a_day' => ':count dīna',
+
+ 'hour' => ':count adīna',
+ 'h' => ':count adīna',
+ 'a_hour' => ':count adīna',
+
+ 'second' => ':count Sekondė',
+ 's' => ':count Sekondė',
+ 'a_second' => ':count Sekondė',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sh.php
new file mode 100644
index 0000000..a953df4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sh.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+// @codeCoverageIgnoreStart
+if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) {
+ \Symfony\Component\Translation\PluralizationRules::set(function ($number) {
+ return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+ }, 'sh');
+}
+// @codeCoverageIgnoreEnd
+
+/*
+ * Authors:
+ * - Томица Кораћ
+ * - Enrique Vidal
+ * - Christopher Dell
+ * - dmilisic
+ * - danijel
+ * - Miroslav Matkovic (mikki021)
+ */
+return [
+ 'diff_now' => 'sada',
+ 'diff_yesterday' => 'juče',
+ 'diff_tomorrow' => 'sutra',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'MMMM D, YYYY',
+ 'LLL' => 'DD MMM HH:mm',
+ 'LLLL' => 'MMMM DD, YYYY HH:mm',
+ ],
+ 'year' => ':count godina|:count godine|:count godina',
+ 'y' => ':count g.',
+ 'month' => ':count mesec|:count meseca|:count meseci',
+ 'm' => ':count m.',
+ 'week' => ':count nedelja|:count nedelje|:count nedelja',
+ 'w' => ':count n.',
+ 'day' => ':count dan|:count dana|:count dana',
+ 'd' => ':count d.',
+ 'hour' => ':count sat|:count sata|:count sati',
+ 'h' => ':count č.',
+ 'minute' => ':count minut|:count minuta|:count minuta',
+ 'min' => ':count min.',
+ 'second' => ':count sekund|:count sekunde|:count sekundi',
+ 's' => ':count s.',
+ 'ago' => 'pre :time',
+ 'from_now' => 'za :time',
+ 'after' => 'nakon :time',
+ 'before' => ':time raniјe',
+ 'weekdays' => ['Nedelja', 'Ponedeljak', 'Utorak', 'Sreda', 'Četvrtak', 'Petak', 'Subota'],
+ 'weekdays_short' => ['Ned', 'Pon', 'Uto', 'Sre', 'Čet', 'Pet', 'Sub'],
+ 'weekdays_min' => ['Ned', 'Pon', 'Uto', 'Sre', 'Čet', 'Pet', 'Sub'],
+ 'months' => ['Januar', 'Februar', 'Mart', 'April', 'Maj', 'Jun', 'Jul', 'Avgust', 'Septembar', 'Oktobar', 'Novembar', 'Decembar'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec'],
+ 'list' => [', ', ' i '],
+ 'meridiem' => ['pre podne', 'po podne'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shi.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shi.php
new file mode 100644
index 0000000..ee5aa0b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shi.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['ⵜⵉⴼⴰⵡⵜ', 'ⵜⴰⴷⴳⴳⵯⴰⵜ'],
+ 'weekdays' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵕⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
+ 'weekdays_short' => ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ', 'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'],
+ 'weekdays_min' => ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ', 'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'],
+ 'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵜⵓⴱⵔ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'],
+ 'months_short' => ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ', 'ⵎⴰⵢ', 'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ', 'ⴽⵜⵓ', 'ⵏⵓⵡ', 'ⴷⵓⵊ'],
+ 'first_day_of_week' => 6,
+ 'weekend' => [5, 6],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+
+ 'year' => ':count aseggwas',
+ 'y' => ':count aseggwas',
+ 'a_year' => ':count aseggwas',
+
+ 'month' => ':count ayyur',
+ 'm' => ':count ayyur',
+ 'a_month' => ':count ayyur',
+
+ 'week' => ':count imalass',
+ 'w' => ':count imalass',
+ 'a_week' => ':count imalass',
+
+ 'day' => ':count ass',
+ 'd' => ':count ass',
+ 'a_day' => ':count ass',
+
+ 'hour' => ':count urɣ', // less reliable
+ 'h' => ':count urɣ', // less reliable
+ 'a_hour' => ':count urɣ', // less reliable
+
+ 'minute' => ':count ⴰⵎⵥⵉ', // less reliable
+ 'min' => ':count ⴰⵎⵥⵉ', // less reliable
+ 'a_minute' => ':count ⴰⵎⵥⵉ', // less reliable
+
+ 'second' => ':count sin', // less reliable
+ 's' => ':count sin', // less reliable
+ 'a_second' => ':count sin', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shi_Latn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shi_Latn.php
new file mode 100644
index 0000000..a5580c3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shi_Latn.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/shi.php', [
+ 'meridiem' => ['tifawt', 'tadggʷat'],
+ 'weekdays' => ['asamas', 'aynas', 'asinas', 'akṛas', 'akwas', 'asimwas', 'asiḍyas'],
+ 'weekdays_short' => ['asa', 'ayn', 'asi', 'akṛ', 'akw', 'asim', 'asiḍ'],
+ 'weekdays_min' => ['asa', 'ayn', 'asi', 'akṛ', 'akw', 'asim', 'asiḍ'],
+ 'months' => ['innayr', 'bṛayṛ', 'maṛṣ', 'ibrir', 'mayyu', 'yunyu', 'yulyuz', 'ɣuct', 'cutanbir', 'ktubr', 'nuwanbir', 'dujanbir'],
+ 'months_short' => ['inn', 'bṛa', 'maṛ', 'ibr', 'may', 'yun', 'yul', 'ɣuc', 'cut', 'ktu', 'nuw', 'duj'],
+ 'first_day_of_week' => 6,
+ 'weekend' => [5, 6],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+
+ 'minute' => ':count agur', // less reliable
+ 'min' => ':count agur', // less reliable
+ 'a_minute' => ':count agur', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shi_Tfng.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shi_Tfng.php
new file mode 100644
index 0000000..e51ed13
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shi_Tfng.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/shi.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shn.php
new file mode 100644
index 0000000..fe7b1ea
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shn.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/shn_MM.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shn_MM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shn_MM.php
new file mode 100644
index 0000000..f399acf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shn_MM.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - ubuntu Myanmar LoCo Team https://ubuntu-mm.net Bone Pyae Sone bone.burma@mail.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'OY MMM OD dddd',
+ ],
+ 'months' => ['လိူၼ်ၵမ်', 'လိူၼ်သၢမ်', 'လိူၼ်သီ', 'လိူၼ်ႁႃႈ', 'လိူၼ်ႁူၵ်း', 'လိူၼ်ၸဵတ်း', 'လိူၼ်ပႅတ်ႇ', 'လိူၼ်ၵဝ်ႈ', 'လိူၼ်သိပ်း', 'လိူၼ်သိပ်းဢိတ်း', 'လိူၼ်သိပ်းဢိတ်းသွင်', 'လိူၼ်ၸဵင်'],
+ 'months_short' => ['လိူၼ်ၵမ်', 'လိူၼ်သၢမ်', 'လိူၼ်သီ', 'လိူၼ်ႁႃႈ', 'လိူၼ်ႁူၵ်း', 'လိူၼ်ၸဵတ်း', 'လိူၼ်ပႅတ်ႇ', 'လိူၼ်ၵဝ်ႈ', 'လိူၼ်သိပ်း', 'လိူၼ်သိပ်းဢိတ်း', 'လိူၼ်သိပ်းဢိတ်းသွင်', 'လိူၼ်ၸဵင်'],
+ 'weekdays' => ['ဝၼ်းဢႃးတိတ်ႉ', 'ဝၼ်းၸၼ်', 'ဝၼ်းဢၢင်းၵၢၼ်း', 'ဝၼ်းပူတ်ႉ', 'ဝၼ်းၽတ်း', 'ဝၼ်းသုၵ်း', 'ဝၼ်းသဝ်'],
+ 'weekdays_short' => ['တိတ့်', 'ၸၼ်', 'ၵၢၼ်း', 'ပုတ့်', 'ၽတ်း', 'သုၵ်း', 'သဝ်'],
+ 'weekdays_min' => ['တိတ့်', 'ၸၼ်', 'ၵၢၼ်း', 'ပုတ့်', 'ၽတ်း', 'သုၵ်း', 'သဝ်'],
+ 'alt_numbers' => ['႐႐', '႐႑', '႐႒', '႐႓', '႐႔', '႐႕', '႐႖', '႐႗', '႐႘', '႐႙', '႑႐', '႑႑', '႑႒', '႑႓', '႑႔', '႑႕', '႑႖', '႑႗', '႑႘', '႑႙', '႒႐', '႒႑', '႒႒', '႒႓', '႒႔', '႒႕', '႒႖', '႒႗', '႒႘', '႒႙', '႓႐', '႓႑', '႓႒', '႓႓', '႓႔', '႓႕', '႓႖', '႓႗', '႓႘', '႓႙', '႔႐', '႔႑', '႔႒', '႔႓', '႔႔', '႔႕', '႔႖', '႔႗', '႔႘', '႔႙', '႕႐', '႕႑', '႕႒', '႕႓', '႕႔', '႕႕', '႕႖', '႕႗', '႕႘', '႕႙', '႖႐', '႖႑', '႖႒', '႖႓', '႖႔', '႖႕', '႖႖', '႖႗', '႖႘', '႖႙', '႗႐', '႗႑', '႗႒', '႗႓', '႗႔', '႗႕', '႗႖', '႗႗', '႗႘', '႗႙', '႘႐', '႘႑', '႘႒', '႘႓', '႘႔', '႘႕', '႘႖', '႘႗', '႘႘', '႘႙', '႙႐', '႙႑', '႙႒', '႙႓', '႙႔', '႙႕', '႙႖', '႙႗', '႙႘', '႙႙'],
+ 'meridiem' => ['ၵၢင်ၼႂ်', 'တၢမ်းၶမ်ႈ'],
+
+ 'month' => ':count လိူၼ်', // less reliable
+ 'm' => ':count လိူၼ်', // less reliable
+ 'a_month' => ':count လိူၼ်', // less reliable
+
+ 'week' => ':count ဝၼ်း', // less reliable
+ 'w' => ':count ဝၼ်း', // less reliable
+ 'a_week' => ':count ဝၼ်း', // less reliable
+
+ 'hour' => ':count ຕີ', // less reliable
+ 'h' => ':count ຕີ', // less reliable
+ 'a_hour' => ':count ຕີ', // less reliable
+
+ 'minute' => ':count ເດັກ', // less reliable
+ 'min' => ':count ເດັກ', // less reliable
+ 'a_minute' => ':count ເດັກ', // less reliable
+
+ 'second' => ':count ဢိုၼ်ႇ', // less reliable
+ 's' => ':count ဢိုၼ်ႇ', // less reliable
+ 'a_second' => ':count ဢိုၼ်ႇ', // less reliable
+
+ 'year' => ':count ပီ',
+ 'y' => ':count ပီ',
+ 'a_year' => ':count ပီ',
+
+ 'day' => ':count ກາງວັນ',
+ 'd' => ':count ກາງວັນ',
+ 'a_day' => ':count ກາງວັນ',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shs.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shs.php
new file mode 100644
index 0000000..8d2e1d7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shs.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/shs_CA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shs_CA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shs_CA.php
new file mode 100644
index 0000000..08d385e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shs_CA.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Neskie Manuel bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['Pellkwet̓min', 'Pelctsipwen̓ten', 'Pellsqépts', 'Peslléwten', 'Pell7ell7é7llqten', 'Pelltspéntsk', 'Pelltqwelq̓wél̓t', 'Pellct̓éxel̓cten', 'Pesqelqlélten', 'Pesllwélsten', 'Pellc7ell7é7llcwten̓', 'Pelltetétq̓em'],
+ 'months_short' => ['Kwe', 'Tsi', 'Sqe', 'Éwt', 'Ell', 'Tsp', 'Tqw', 'Ct̓é', 'Qel', 'Wél', 'U7l', 'Tet'],
+ 'weekdays' => ['Sxetspesq̓t', 'Spetkesq̓t', 'Selesq̓t', 'Skellesq̓t', 'Smesesq̓t', 'Stselkstesq̓t', 'Stqmekstesq̓t'],
+ 'weekdays_short' => ['Sxe', 'Spe', 'Sel', 'Ske', 'Sme', 'Sts', 'Stq'],
+ 'weekdays_min' => ['Sxe', 'Spe', 'Sel', 'Ske', 'Sme', 'Sts', 'Stq'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count sqlélten', // less reliable
+ 'y' => ':count sqlélten', // less reliable
+ 'a_year' => ':count sqlélten', // less reliable
+
+ 'month' => ':count swewll', // less reliable
+ 'm' => ':count swewll', // less reliable
+ 'a_month' => ':count swewll', // less reliable
+
+ 'hour' => ':count seqwlút', // less reliable
+ 'h' => ':count seqwlút', // less reliable
+ 'a_hour' => ':count seqwlút', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/si.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/si.php
new file mode 100644
index 0000000..289d4d5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/si.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Serhan Apaydın
+ * - JD Isaacks
+ * - Malinda Weerasinghe (MalindaWMD)
+ */
+return [
+ 'year' => '{1}වසර 1|වසර :count',
+ 'a_year' => '{1}වසරක්|වසර :count',
+ 'month' => '{1}මාස 1|මාස :count',
+ 'a_month' => '{1}මාසය|මාස :count',
+ 'week' => '{1}සති 1|සති :count',
+ 'a_week' => '{1}සතියක්|සති :count',
+ 'day' => '{1}දින 1|දින :count',
+ 'a_day' => '{1}දිනක්|දින :count',
+ 'hour' => '{1}පැය 1|පැය :count',
+ 'a_hour' => '{1}පැයක්|පැය :count',
+ 'minute' => '{1}මිනිත්තු 1|මිනිත්තු :count',
+ 'a_minute' => '{1}මිනිත්තුවක්|මිනිත්තු :count',
+ 'second' => '{1}තත්පර 1|තත්පර :count',
+ 'a_second' => '{1}තත්පර කිහිපයකට|තත්පර :count',
+ 'ago' => ':time කට පෙර',
+ 'from_now' => function ($time) {
+ if (preg_match('/දින \d+/', $time)) {
+ return $time.' න්';
+ }
+
+ return $time.' කින්';
+ },
+ 'before' => ':time කට පෙර',
+ 'after' => function ($time) {
+ if (preg_match('/දින \d+/', $time)) {
+ return $time.' න්';
+ }
+
+ return $time.' කින්';
+ },
+ 'diff_now' => 'දැන්',
+ 'diff_today' => 'අද',
+ 'diff_yesterday' => 'ඊයේ',
+ 'diff_tomorrow' => 'හෙට',
+ 'formats' => [
+ 'LT' => 'a h:mm',
+ 'LTS' => 'a h:mm:ss',
+ 'L' => 'YYYY/MM/DD',
+ 'LL' => 'YYYY MMMM D',
+ 'LLL' => 'YYYY MMMM D, a h:mm',
+ 'LLLL' => 'YYYY MMMM D [වැනි] dddd, a h:mm:ss',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[අද] LT[ට]',
+ 'nextDay' => '[හෙට] LT[ට]',
+ 'nextWeek' => 'dddd LT[ට]',
+ 'lastDay' => '[ඊයේ] LT[ට]',
+ 'lastWeek' => '[පසුගිය] dddd LT[ට]',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number වැනි',
+ 'meridiem' => ['පෙර වරු', 'පස් වරු', 'පෙ.ව.', 'ප.ව.'],
+ 'months' => ['ජනවාරි', 'පෙබරවාරි', 'මාර්තු', 'අප්රේල්', 'මැයි', 'ජූනි', 'ජූලි', 'අගෝස්තු', 'සැප්තැම්බර්', 'ඔක්තෝබර්', 'නොවැම්බර්', 'දෙසැම්බර්'],
+ 'months_short' => ['ජන', 'පෙබ', 'මාර්', 'අප්', 'මැයි', 'ජූනි', 'ජූලි', 'අගෝ', 'සැප්', 'ඔක්', 'නොවැ', 'දෙසැ'],
+ 'weekdays' => ['ඉරිදා', 'සඳුදා', 'අඟහරුවාදා', 'බදාදා', 'බ්රහස්පතින්දා', 'සිකුරාදා', 'සෙනසුරාදා'],
+ 'weekdays_short' => ['ඉරි', 'සඳු', 'අඟ', 'බදා', 'බ්රහ', 'සිකු', 'සෙන'],
+ 'weekdays_min' => ['ඉ', 'ස', 'අ', 'බ', 'බ්ර', 'සි', 'සෙ'],
+ 'first_day_of_week' => 1,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/si_LK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/si_LK.php
new file mode 100644
index 0000000..6c5be97
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/si_LK.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/si.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sid.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sid.php
new file mode 100644
index 0000000..b1c6521
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sid.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/sid_ET.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sid_ET.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sid_ET.php
new file mode 100644
index 0000000..1296f9b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sid_ET.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ 'weekdays' => ['Sambata', 'Sanyo', 'Maakisanyo', 'Roowe', 'Hamuse', 'Arbe', 'Qidaame'],
+ 'weekdays_short' => ['Sam', 'San', 'Mak', 'Row', 'Ham', 'Arb', 'Qid'],
+ 'weekdays_min' => ['Sam', 'San', 'Mak', 'Row', 'Ham', 'Arb', 'Qid'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['soodo', 'hawwaro'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sk.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sk.php
new file mode 100644
index 0000000..fd0f6b3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sk.php
@@ -0,0 +1,81 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - Martin Suja
+ * - Tsutomu Kuroda
+ * - tjku
+ * - Max Melentiev
+ * - Juanito Fatas
+ * - Ivan Stana
+ * - Akira Matsuda
+ * - Christopher Dell
+ * - James McKinney
+ * - Enrique Vidal
+ * - Simone Carletti
+ * - Aaron Patterson
+ * - Jozef Fulop
+ * - Nicolás Hock Isaza
+ * - Tom Hughes
+ * - Simon Hürlimann (CyT)
+ * - jofi
+ * - Jakub ADAMEC
+ * - Marek Adamický
+ */
+return [
+ 'year' => 'rok|:count roky|:count rokov',
+ 'y' => ':count r',
+ 'month' => 'mesiac|:count mesiace|:count mesiacov',
+ 'm' => ':count m',
+ 'week' => 'týždeň|:count týždne|:count týždňov',
+ 'w' => ':count t',
+ 'day' => 'deň|:count dni|:count dní',
+ 'd' => ':count d',
+ 'hour' => 'hodinu|:count hodiny|:count hodín',
+ 'h' => ':count h',
+ 'minute' => 'minútu|:count minúty|:count minút',
+ 'min' => ':count min',
+ 'second' => 'sekundu|:count sekundy|:count sekúnd',
+ 's' => ':count s',
+ 'ago' => 'pred :time',
+ 'from_now' => 'za :time',
+ 'after' => 'o :time neskôr',
+ 'before' => ':time predtým',
+ 'year_ago' => 'rokom|:count rokmi|:count rokmi',
+ 'month_ago' => 'mesiacom|:count mesiacmi|:count mesiacmi',
+ 'week_ago' => 'týždňom|:count týždňami|:count týždňami',
+ 'day_ago' => 'dňom|:count dňami|:count dňami',
+ 'hour_ago' => 'hodinou|:count hodinami|:count hodinami',
+ 'minute_ago' => 'minútou|:count minútami|:count minútami',
+ 'second_ago' => 'sekundou|:count sekundami|:count sekundami',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' a '],
+ 'diff_now' => 'teraz',
+ 'diff_yesterday' => 'včera',
+ 'diff_tomorrow' => 'zajtra',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'DD. MMMM YYYY',
+ 'LLL' => 'D. M. HH:mm',
+ 'LLLL' => 'dddd D. MMMM YYYY HH:mm',
+ ],
+ 'weekdays' => ['nedeľa', 'pondelok', 'utorok', 'streda', 'štvrtok', 'piatok', 'sobota'],
+ 'weekdays_short' => ['ne', 'po', 'ut', 'st', 'št', 'pi', 'so'],
+ 'weekdays_min' => ['ne', 'po', 'ut', 'st', 'št', 'pi', 'so'],
+ 'months' => ['január', 'február', 'marec', 'apríl', 'máj', 'jún', 'júl', 'august', 'september', 'október', 'november', 'december'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'máj', 'jún', 'júl', 'aug', 'sep', 'okt', 'nov', 'dec'],
+ 'meridiem' => ['dopoludnia', 'popoludní'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sk_SK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sk_SK.php
new file mode 100644
index 0000000..be3d1f2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sk_SK.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/sk.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sl.php
new file mode 100644
index 0000000..56d0f1b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sl.php
@@ -0,0 +1,126 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - Tsutomu Kuroda
+ * - tjku
+ * - Max Melentiev
+ * - Juanito Fatas
+ * - Akira Matsuda
+ * - Christopher Dell
+ * - Enrique Vidal
+ * - Simone Carletti
+ * - Aaron Patterson
+ * - Nicolás Hock Isaza
+ * - Miha Rebernik
+ * - Gal Jakič (morpheus7CS)
+ * - Glavić
+ * - Anže Časar
+ * - Lovro Tramšek (Lovro1107)
+ * - burut13
+ */
+return [
+ 'year' => ':count leto|:count leti|:count leta|:count let',
+ 'y' => ':count leto|:count leti|:count leta|:count let',
+ 'month' => ':count mesec|:count meseca|:count mesece|:count mesecev',
+ 'm' => ':count mes.',
+ 'week' => ':count teden|:count tedna|:count tedne|:count tednov',
+ 'w' => ':count ted.',
+ 'day' => ':count dan|:count dni|:count dni|:count dni',
+ 'd' => ':count dan|:count dni|:count dni|:count dni',
+ 'hour' => ':count ura|:count uri|:count ure|:count ur',
+ 'h' => ':count h',
+ 'minute' => ':count minuta|:count minuti|:count minute|:count minut',
+ 'min' => ':count min.',
+ 'second' => ':count sekunda|:count sekundi|:count sekunde|:count sekund',
+ 'a_second' => '{1}nekaj sekund|:count sekunda|:count sekundi|:count sekunde|:count sekund',
+ 's' => ':count s',
+
+ 'year_ago' => ':count letom|:count leti|:count leti|:count leti',
+ 'y_ago' => ':count letom|:count leti|:count leti|:count leti',
+ 'month_ago' => ':count mesecem|:count meseci|:count meseci|:count meseci',
+ 'week_ago' => ':count tednom|:count tednoma|:count tedni|:count tedni',
+ 'day_ago' => ':count dnem|:count dnevoma|:count dnevi|:count dnevi',
+ 'd_ago' => ':count dnem|:count dnevoma|:count dnevi|:count dnevi',
+ 'hour_ago' => ':count uro|:count urama|:count urami|:count urami',
+ 'minute_ago' => ':count minuto|:count minutama|:count minutami|:count minutami',
+ 'second_ago' => ':count sekundo|:count sekundama|:count sekundami|:count sekundami',
+
+ 'day_from_now' => ':count dan|:count dneva|:count dni|:count dni',
+ 'd_from_now' => ':count dan|:count dneva|:count dni|:count dni',
+ 'hour_from_now' => ':count uro|:count uri|:count ure|:count ur',
+ 'minute_from_now' => ':count minuto|:count minuti|:count minute|:count minut',
+ 'second_from_now' => ':count sekundo|:count sekundi|:count sekunde|:count sekund',
+
+ 'ago' => 'pred :time',
+ 'from_now' => 'čez :time',
+ 'after' => ':time kasneje',
+ 'before' => ':time prej',
+
+ 'diff_now' => 'ravnokar',
+ 'diff_today' => 'danes',
+ 'diff_today_regexp' => 'danes(?:\\s+ob)?',
+ 'diff_yesterday' => 'včeraj',
+ 'diff_yesterday_regexp' => 'včeraj(?:\\s+ob)?',
+ 'diff_tomorrow' => 'jutri',
+ 'diff_tomorrow_regexp' => 'jutri(?:\\s+ob)?',
+ 'diff_before_yesterday' => 'predvčerajšnjim',
+ 'diff_after_tomorrow' => 'pojutrišnjem',
+
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'period_start_date' => 'od :date',
+ 'period_end_date' => 'do :date',
+
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY H:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[danes ob] LT',
+ 'nextDay' => '[jutri ob] LT',
+ 'nextWeek' => 'dddd [ob] LT',
+ 'lastDay' => '[včeraj ob] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[preteklo] [nedeljo] [ob] LT';
+ case 1:
+ return '[pretekli] [ponedeljek] [ob] LT';
+ case 2:
+ return '[pretekli] [torek] [ob] LT';
+ case 3:
+ return '[preteklo] [sredo] [ob] LT';
+ case 4:
+ return '[pretekli] [četrtek] [ob] LT';
+ case 5:
+ return '[pretekli] [petek] [ob] LT';
+ case 6:
+ return '[preteklo] [soboto] [ob] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['januar', 'februar', 'marec', 'april', 'maj', 'junij', 'julij', 'avgust', 'september', 'oktober', 'november', 'december'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'avg', 'sep', 'okt', 'nov', 'dec'],
+ 'weekdays' => ['nedelja', 'ponedeljek', 'torek', 'sreda', 'četrtek', 'petek', 'sobota'],
+ 'weekdays_short' => ['ned', 'pon', 'tor', 'sre', 'čet', 'pet', 'sob'],
+ 'weekdays_min' => ['ne', 'po', 'to', 'sr', 'če', 'pe', 'so'],
+ 'list' => [', ', ' in '],
+ 'meridiem' => ['dopoldan', 'popoldan'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sl_SI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sl_SI.php
new file mode 100644
index 0000000..da9fef0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sl_SI.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/sl.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sm.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sm.php
new file mode 100644
index 0000000..e8c118a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sm.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/sm_WS.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sm_WS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sm_WS.php
new file mode 100644
index 0000000..f066068
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sm_WS.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Ianuari', 'Fepuari', 'Mati', 'Aperila', 'Me', 'Iuni', 'Iulai', 'Auguso', 'Setema', 'Oketopa', 'Novema', 'Tesema'],
+ 'months_short' => ['Ian', 'Fep', 'Mat', 'Ape', 'Me', 'Iun', 'Iul', 'Aug', 'Set', 'Oke', 'Nov', 'Tes'],
+ 'weekdays' => ['Aso Sa', 'Aso Gafua', 'Aso Lua', 'Aso Lulu', 'Aso Tofi', 'Aso Farail', 'Aso To\'ana\'i'],
+ 'weekdays_short' => ['Aso Sa', 'Aso Gaf', 'Aso Lua', 'Aso Lul', 'Aso Tof', 'Aso Far', 'Aso To\''],
+ 'weekdays_min' => ['Aso Sa', 'Aso Gaf', 'Aso Lua', 'Aso Lul', 'Aso Tof', 'Aso Far', 'Aso To\''],
+
+ 'hour' => ':count uati', // less reliable
+ 'h' => ':count uati', // less reliable
+ 'a_hour' => ':count uati', // less reliable
+
+ 'minute' => ':count itiiti', // less reliable
+ 'min' => ':count itiiti', // less reliable
+ 'a_minute' => ':count itiiti', // less reliable
+
+ 'second' => ':count lua', // less reliable
+ 's' => ':count lua', // less reliable
+ 'a_second' => ':count lua', // less reliable
+
+ 'year' => ':count tausaga',
+ 'y' => ':count tausaga',
+ 'a_year' => ':count tausaga',
+
+ 'month' => ':count māsina',
+ 'm' => ':count māsina',
+ 'a_month' => ':count māsina',
+
+ 'week' => ':count vaiaso',
+ 'w' => ':count vaiaso',
+ 'a_week' => ':count vaiaso',
+
+ 'day' => ':count aso',
+ 'd' => ':count aso',
+ 'a_day' => ':count aso',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/smn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/smn.php
new file mode 100644
index 0000000..b252ebb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/smn.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['ip.', 'ep.'],
+ 'weekdays' => ['pasepeeivi', 'vuossaargâ', 'majebaargâ', 'koskoho', 'tuorâstuv', 'vástuppeeivi', 'lávurduv'],
+ 'weekdays_short' => ['pas', 'vuo', 'maj', 'kos', 'tuo', 'vás', 'láv'],
+ 'weekdays_min' => ['pa', 'vu', 'ma', 'ko', 'tu', 'vá', 'lá'],
+ 'weekdays_standalone' => ['pasepeivi', 'vuossargâ', 'majebargâ', 'koskokko', 'tuorâstâh', 'vástuppeivi', 'lávurdâh'],
+ 'months' => ['uđđâivemáánu', 'kuovâmáánu', 'njuhčâmáánu', 'cuáŋuimáánu', 'vyesimáánu', 'kesimáánu', 'syeinimáánu', 'porgemáánu', 'čohčâmáánu', 'roovvâdmáánu', 'skammâmáánu', 'juovlâmáánu'],
+ 'months_short' => ['uđiv', 'kuovâ', 'njuhčâ', 'cuáŋui', 'vyesi', 'kesi', 'syeini', 'porge', 'čohčâ', 'roovvâd', 'skammâ', 'juovlâ'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'H.mm',
+ 'LTS' => 'H.mm.ss',
+ 'L' => 'D.M.YYYY',
+ 'LL' => 'MMM D. YYYY',
+ 'LLL' => 'MMMM D. YYYY H.mm',
+ 'LLLL' => 'dddd, MMMM D. YYYY H.mm',
+ ],
+
+ 'hour' => ':count äigi', // less reliable
+ 'h' => ':count äigi', // less reliable
+ 'a_hour' => ':count äigi', // less reliable
+
+ 'year' => ':count ihe',
+ 'y' => ':count ihe',
+ 'a_year' => ':count ihe',
+
+ 'month' => ':count mánuppaje',
+ 'm' => ':count mánuppaje',
+ 'a_month' => ':count mánuppaje',
+
+ 'week' => ':count okko',
+ 'w' => ':count okko',
+ 'a_week' => ':count okko',
+
+ 'day' => ':count peivi',
+ 'd' => ':count peivi',
+ 'a_day' => ':count peivi',
+
+ 'minute' => ':count miinut',
+ 'min' => ':count miinut',
+ 'a_minute' => ':count miinut',
+
+ 'second' => ':count nubbe',
+ 's' => ':count nubbe',
+ 'a_second' => ':count nubbe',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sn.php
new file mode 100644
index 0000000..62c82b1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sn.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['a', 'p'],
+ 'weekdays' => ['Svondo', 'Muvhuro', 'Chipiri', 'Chitatu', 'China', 'Chishanu', 'Mugovera'],
+ 'weekdays_short' => ['Svo', 'Muv', 'Chp', 'Cht', 'Chn', 'Chs', 'Mug'],
+ 'weekdays_min' => ['Sv', 'Mu', 'Cp', 'Ct', 'Cn', 'Cs', 'Mg'],
+ 'months' => ['Ndira', 'Kukadzi', 'Kurume', 'Kubvumbi', 'Chivabvu', 'Chikumi', 'Chikunguru', 'Nyamavhuvhu', 'Gunyana', 'Gumiguru', 'Mbudzi', 'Zvita'],
+ 'months_short' => ['Ndi', 'Kuk', 'Kur', 'Kub', 'Chv', 'Chk', 'Chg', 'Nya', 'Gun', 'Gum', 'Mbu', 'Zvi'],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-dd',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'YYYY MMMM D HH:mm',
+ 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
+ ],
+
+ 'year' => 'makore :count',
+ 'y' => 'makore :count',
+ 'a_year' => 'makore :count',
+
+ 'month' => 'mwedzi :count',
+ 'm' => 'mwedzi :count',
+ 'a_month' => 'mwedzi :count',
+
+ 'week' => 'vhiki :count',
+ 'w' => 'vhiki :count',
+ 'a_week' => 'vhiki :count',
+
+ 'day' => 'mazuva :count',
+ 'd' => 'mazuva :count',
+ 'a_day' => 'mazuva :count',
+
+ 'hour' => 'maawa :count',
+ 'h' => 'maawa :count',
+ 'a_hour' => 'maawa :count',
+
+ 'minute' => 'minitsi :count',
+ 'min' => 'minitsi :count',
+ 'a_minute' => 'minitsi :count',
+
+ 'second' => 'sekonzi :count',
+ 's' => 'sekonzi :count',
+ 'a_second' => 'sekonzi :count',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so.php
new file mode 100644
index 0000000..5785271
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Author:
+ * - Abdifatah Abdilahi(@abdifatahz)
+ */
+return [
+ 'year' => ':count sanad|:count sanadood',
+ 'a_year' => 'sanad|:count sanadood',
+ 'y' => '{1}:countsn|{0}:countsns|]1,Inf[:countsn',
+ 'month' => ':count bil|:count bilood',
+ 'a_month' => 'bil|:count bilood',
+ 'm' => ':countbil',
+ 'week' => ':count isbuuc',
+ 'a_week' => 'isbuuc|:count isbuuc',
+ 'w' => ':countis',
+ 'day' => ':count maalin|:count maalmood',
+ 'a_day' => 'maalin|:count maalmood',
+ 'd' => ':countml',
+ 'hour' => ':count saac',
+ 'a_hour' => 'saacad|:count saac',
+ 'h' => ':countsc',
+ 'minute' => ':count daqiiqo',
+ 'a_minute' => 'daqiiqo|:count daqiiqo',
+ 'min' => ':countdq',
+ 'second' => ':count ilbidhiqsi',
+ 'a_second' => 'xooga ilbidhiqsiyo|:count ilbidhiqsi',
+ 's' => ':countil',
+ 'ago' => ':time kahor',
+ 'from_now' => ':time gudahood',
+ 'after' => ':time kedib',
+ 'before' => ':time kahor',
+ 'diff_now' => 'hada',
+ 'diff_today' => 'maanta',
+ 'diff_today_regexp' => 'maanta(?:\s+markay\s+(?:tahay|ahayd))?',
+ 'diff_yesterday' => 'shalayto',
+ 'diff_yesterday_regexp' => 'shalayto(?:\s+markay\s+ahayd)?',
+ 'diff_tomorrow' => 'beri',
+ 'diff_tomorrow_regexp' => 'beri(?:\s+markay\s+tahay)?',
+ 'diff_before_yesterday' => 'doraato',
+ 'diff_after_tomorrow' => 'saadanbe',
+ 'period_recurrences' => 'mar|:count jeer',
+ 'period_interval' => ':interval kasta',
+ 'period_start_date' => 'laga bilaabo :date',
+ 'period_end_date' => 'ilaa :date',
+ 'months' => ['Janaayo', 'Febraayo', 'Abriil', 'Maajo', 'Juun', 'Luuliyo', 'Agoosto', 'Sebteembar', 'Oktoobar', 'Nofeembar', 'Diseembar'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Abr', 'Mjo', 'Jun', 'Lyo', 'Agt', 'Seb', 'Okt', 'Nof', 'Dis'],
+ 'weekdays' => ['Axad', 'Isniin', 'Talaada', 'Arbaca', 'Khamiis', 'Jimce', 'Sabti'],
+ 'weekdays_short' => ['Axd', 'Isn', 'Tal', 'Arb', 'Kha', 'Jim', 'Sbt'],
+ 'weekdays_min' => ['Ax', 'Is', 'Ta', 'Ar', 'Kh', 'Ji', 'Sa'],
+ 'list' => [', ', ' and '],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Maanta markay tahay] LT',
+ 'nextDay' => '[Beri markay tahay] LT',
+ 'nextWeek' => 'dddd [markay tahay] LT',
+ 'lastDay' => '[Shalay markay ahayd] LT',
+ 'lastWeek' => '[Hore] dddd [Markay ahayd] LT',
+ 'sameElse' => 'L',
+ ],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_DJ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_DJ.php
new file mode 100644
index 0000000..273dda8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_DJ.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/so.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_ET.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_ET.php
new file mode 100644
index 0000000..7b69971
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_ET.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return require __DIR__.'/so.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_KE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_KE.php
new file mode 100644
index 0000000..7b69971
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_KE.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return require __DIR__.'/so.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_SO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_SO.php
new file mode 100644
index 0000000..7b69971
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/so_SO.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return require __DIR__.'/so.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq.php
new file mode 100644
index 0000000..ffa592e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - JD Isaacks
+ * - Fadion Dashi
+ */
+return [
+ 'year' => ':count vit|:count vjet',
+ 'a_year' => 'një vit|:count vite',
+ 'y' => ':count v.',
+ 'month' => ':count muaj',
+ 'a_month' => 'një muaj|:count muaj',
+ 'm' => ':count muaj',
+ 'week' => ':count javë',
+ 'a_week' => ':count javë|:count javë',
+ 'w' => ':count j.',
+ 'day' => ':count ditë',
+ 'a_day' => 'një ditë|:count ditë',
+ 'd' => ':count d.',
+ 'hour' => ':count orë',
+ 'a_hour' => 'një orë|:count orë',
+ 'h' => ':count o.',
+ 'minute' => ':count minutë|:count minuta',
+ 'a_minute' => 'një minutë|:count minuta',
+ 'min' => ':count min.',
+ 'second' => ':count sekondë|:count sekonda',
+ 'a_second' => 'disa sekonda|:count sekonda',
+ 's' => ':count s.',
+ 'ago' => ':time më parë',
+ 'from_now' => 'në :time',
+ 'after' => ':time pas',
+ 'before' => ':time para',
+ 'diff_now' => 'tani',
+ 'diff_today' => 'Sot',
+ 'diff_today_regexp' => 'Sot(?:\\s+në)?',
+ 'diff_yesterday' => 'dje',
+ 'diff_yesterday_regexp' => 'Dje(?:\\s+në)?',
+ 'diff_tomorrow' => 'nesër',
+ 'diff_tomorrow_regexp' => 'Nesër(?:\\s+në)?',
+ 'diff_before_yesterday' => 'pardje',
+ 'diff_after_tomorrow' => 'pasnesër',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Sot në] LT',
+ 'nextDay' => '[Nesër në] LT',
+ 'nextWeek' => 'dddd [në] LT',
+ 'lastDay' => '[Dje në] LT',
+ 'lastWeek' => 'dddd [e kaluar në] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'meridiem' => ['PD', 'MD'],
+ 'months' => ['janar', 'shkurt', 'mars', 'prill', 'maj', 'qershor', 'korrik', 'gusht', 'shtator', 'tetor', 'nëntor', 'dhjetor'],
+ 'months_short' => ['jan', 'shk', 'mar', 'pri', 'maj', 'qer', 'kor', 'gus', 'sht', 'tet', 'nën', 'dhj'],
+ 'weekdays' => ['e diel', 'e hënë', 'e martë', 'e mërkurë', 'e enjte', 'e premte', 'e shtunë'],
+ 'weekdays_short' => ['die', 'hën', 'mar', 'mër', 'enj', 'pre', 'sht'],
+ 'weekdays_min' => ['d', 'h', 'ma', 'më', 'e', 'p', 'sh'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' dhe '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq_AL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq_AL.php
new file mode 100644
index 0000000..0bfbdf3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq_AL.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/sq.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq_MK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq_MK.php
new file mode 100644
index 0000000..c844fe0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq_MK.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/sq.php', [
+ 'formats' => [
+ 'L' => 'D.M.YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY, HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq_XK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq_XK.php
new file mode 100644
index 0000000..c844fe0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sq_XK.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/sq.php', [
+ 'formats' => [
+ 'L' => 'D.M.YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY, HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr.php
new file mode 100644
index 0000000..6ecf2d0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr.php
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - shaishavgandhi05
+ * - Serhan Apaydın
+ * - JD Isaacks
+ * - Glavić
+ * - Milos Sakovic
+ */
+return [
+ 'year' => ':count godina|:count godine|:count godina',
+ 'y' => ':count g.',
+ 'month' => ':count mesec|:count meseca|:count meseci',
+ 'm' => ':count mj.',
+ 'week' => ':count nedelja|:count nedelje|:count nedelja',
+ 'w' => ':count ned.',
+ 'day' => ':count dan|:count dana|:count dana',
+ 'd' => ':count d.',
+ 'hour' => ':count sat|:count sata|:count sati',
+ 'h' => ':count č.',
+ 'minute' => ':count minut|:count minuta|:count minuta',
+ 'min' => ':count min.',
+ 'second' => ':count sekundu|:count sekunde|:count sekundi',
+ 's' => ':count sek.',
+ 'ago' => 'pre :time',
+ 'from_now' => 'za :time',
+ 'after' => 'nakon :time',
+ 'before' => 'pre :time',
+
+ 'year_from_now' => ':count godinu|:count godine|:count godina',
+ 'year_ago' => ':count godinu|:count godine|:count godina',
+ 'week_from_now' => ':count nedelju|:count nedelje|:count nedelja',
+ 'week_ago' => ':count nedelju|:count nedelje|:count nedelja',
+
+ 'diff_now' => 'upravo sada',
+ 'diff_today' => 'danas',
+ 'diff_today_regexp' => 'danas(?:\\s+u)?',
+ 'diff_yesterday' => 'juče',
+ 'diff_yesterday_regexp' => 'juče(?:\\s+u)?',
+ 'diff_tomorrow' => 'sutra',
+ 'diff_tomorrow_regexp' => 'sutra(?:\\s+u)?',
+ 'diff_before_yesterday' => 'prekjuče',
+ 'diff_after_tomorrow' => 'preksutra',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY H:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[danas u] LT',
+ 'nextDay' => '[sutra u] LT',
+ 'nextWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[u nedelju u] LT';
+ case 3:
+ return '[u sredu u] LT';
+ case 6:
+ return '[u subotu u] LT';
+ default:
+ return '[u] dddd [u] LT';
+ }
+ },
+ 'lastDay' => '[juče u] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[prošle nedelje u] LT';
+ case 1:
+ return '[prošlog ponedeljka u] LT';
+ case 2:
+ return '[prošlog utorka u] LT';
+ case 3:
+ return '[prošle srede u] LT';
+ case 4:
+ return '[prošlog četvrtka u] LT';
+ case 5:
+ return '[prošlog petka u] LT';
+ default:
+ return '[prošle subote u] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
+ 'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'],
+ 'weekdays' => ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'],
+ 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'],
+ 'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' i '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php
new file mode 100644
index 0000000..8540742
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - shaishavgandhi05
+ * - Serhan Apaydın
+ * - JD Isaacks
+ * - Glavić
+ * - Nikola Zeravcic
+ * - Milos Sakovic
+ */
+return [
+ 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
+ 'y' => ':count г.',
+ 'month' => '{1}:count месец|{2,3,4}:count месеца|[0,Inf[:count месеци',
+ 'm' => ':count м.',
+ 'week' => '{1}:count недеља|{2,3,4}:count недеље|[0,Inf[:count недеља',
+ 'w' => ':count нед.',
+ 'day' => '{1,21,31}:count дан|[0,Inf[:count дана',
+ 'd' => ':count д.',
+ 'hour' => '{1,21}:count сат|{2,3,4,22,23,24}:count сата|[0,Inf[:count сати',
+ 'h' => ':count ч.',
+ 'minute' => '{1,21,31,41,51}:count минут|[0,Inf[:count минута',
+ 'min' => ':count мин.',
+ 'second' => '{1,21,31,41,51}:count секунд|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count секунде|[0,Inf[:count секунди',
+ 's' => ':count сек.',
+ 'ago' => 'пре :time',
+ 'from_now' => 'за :time',
+ 'after' => ':time након',
+ 'before' => ':time пре',
+ 'year_from_now' => '{1,21,31,41,51}:count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
+ 'year_ago' => '{1,21,31,41,51}:count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
+ 'week_from_now' => '{1}:count недељу|{2,3,4}:count недеље|[0,Inf[:count недеља',
+ 'week_ago' => '{1}:count недељу|{2,3,4}:count недеље|[0,Inf[:count недеља',
+ 'diff_now' => 'управо сада',
+ 'diff_today' => 'данас',
+ 'diff_today_regexp' => 'данас(?:\\s+у)?',
+ 'diff_yesterday' => 'јуче',
+ 'diff_yesterday_regexp' => 'јуче(?:\\s+у)?',
+ 'diff_tomorrow' => 'сутра',
+ 'diff_tomorrow_regexp' => 'сутра(?:\\s+у)?',
+ 'diff_before_yesterday' => 'прекјуче',
+ 'diff_after_tomorrow' => 'прекосутра',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY H:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[данас у] LT',
+ 'nextDay' => '[сутра у] LT',
+ 'nextWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[у недељу у] LT';
+ case 3:
+ return '[у среду у] LT';
+ case 6:
+ return '[у суботу у] LT';
+ default:
+ return '[у] dddd [у] LT';
+ }
+ },
+ 'lastDay' => '[јуче у] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[прошле недеље у] LT';
+ case 1:
+ return '[прошлог понедељка у] LT';
+ case 2:
+ return '[прошлог уторка у] LT';
+ case 3:
+ return '[прошле среде у] LT';
+ case 4:
+ return '[прошлог четвртка у] LT';
+ case 5:
+ return '[прошлог петка у] LT';
+ default:
+ return '[прошле суботе у] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'],
+ 'months_short' => ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'],
+ 'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
+ 'weekdays_short' => ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'],
+ 'weekdays_min' => ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' и '],
+ 'meridiem' => ['АМ', 'ПМ'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_BA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_BA.php
new file mode 100644
index 0000000..36405d3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_BA.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/sr_Cyrl.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D.M.yy.',
+ 'LL' => 'DD.MM.YYYY.',
+ 'LLL' => 'DD. MMMM YYYY. HH:mm',
+ 'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm',
+ ],
+ 'weekdays' => ['недјеља', 'понедељак', 'уторак', 'сриједа', 'четвртак', 'петак', 'субота'],
+ 'weekdays_short' => ['нед.', 'пон.', 'ут.', 'ср.', 'чет.', 'пет.', 'суб.'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php
new file mode 100644
index 0000000..fb6179e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Glavić
+ * - Milos Sakovic
+ */
+return [
+ 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
+ 'y' => ':count г.',
+ 'month' => '{1}:count мјесец|{2,3,4}:count мјесеца|[0,Inf[:count мјесеци',
+ 'm' => ':count мј.',
+ 'week' => '{1}:count недјеља|{2,3,4}:count недјеље|[0,Inf[:count недјеља',
+ 'w' => ':count нед.',
+ 'day' => '{1,21,31}:count дан|[0,Inf[:count дана',
+ 'd' => ':count д.',
+ 'hour' => '{1,21}:count сат|{2,3,4,22,23,24}:count сата|[0,Inf[:count сати',
+ 'h' => ':count ч.',
+ 'minute' => '{1,21,31,41,51}:count минут|[0,Inf[:count минута',
+ 'min' => ':count мин.',
+ 'second' => '{1,21,31,41,51}:count секунд|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count секунде|[0,Inf[:count секунди',
+ 's' => ':count сек.',
+ 'ago' => 'прије :time',
+ 'from_now' => 'за :time',
+ 'after' => ':time након',
+ 'before' => ':time прије',
+
+ 'year_from_now' => '{1,21,31,41,51}:count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
+ 'year_ago' => '{1,21,31,41,51}:count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[:count година',
+
+ 'week_from_now' => '{1}:count недјељу|{2,3,4}:count недјеље|[0,Inf[:count недјеља',
+ 'week_ago' => '{1}:count недјељу|{2,3,4}:count недјеље|[0,Inf[:count недјеља',
+
+ 'diff_now' => 'управо сада',
+ 'diff_today' => 'данас',
+ 'diff_today_regexp' => 'данас(?:\\s+у)?',
+ 'diff_yesterday' => 'јуче',
+ 'diff_yesterday_regexp' => 'јуче(?:\\s+у)?',
+ 'diff_tomorrow' => 'сутра',
+ 'diff_tomorrow_regexp' => 'сутра(?:\\s+у)?',
+ 'diff_before_yesterday' => 'прекјуче',
+ 'diff_after_tomorrow' => 'прекосјутра',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM YYYY',
+ 'LLL' => 'D. MMMM YYYY H:mm',
+ 'LLLL' => 'dddd, D. MMMM YYYY H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[данас у] LT',
+ 'nextDay' => '[сутра у] LT',
+ 'nextWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[у недељу у] LT';
+ case 3:
+ return '[у среду у] LT';
+ case 6:
+ return '[у суботу у] LT';
+ default:
+ return '[у] dddd [у] LT';
+ }
+ },
+ 'lastDay' => '[јуче у] LT',
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[прошле недеље у] LT';
+ case 1:
+ return '[прошлог понедељка у] LT';
+ case 2:
+ return '[прошлог уторка у] LT';
+ case 3:
+ return '[прошле среде у] LT';
+ case 4:
+ return '[прошлог четвртка у] LT';
+ case 5:
+ return '[прошлог петка у] LT';
+ default:
+ return '[прошле суботе у] LT';
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'],
+ 'months_short' => ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'],
+ 'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
+ 'weekdays_short' => ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'],
+ 'weekdays_min' => ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' и '],
+ 'meridiem' => ['АМ', 'ПМ'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_XK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_XK.php
new file mode 100644
index 0000000..0643a41
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_XK.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/sr_Cyrl_BA.php', [
+ 'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn.php
new file mode 100644
index 0000000..8ae8c41
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/sr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_BA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_BA.php
new file mode 100644
index 0000000..c25a507
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_BA.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/sr_Latn.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D.M.yy.',
+ 'LL' => 'DD.MM.YYYY.',
+ 'LLL' => 'DD. MMMM YYYY. HH:mm',
+ 'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm',
+ ],
+ 'weekdays' => ['nedjelja', 'ponedeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
+ 'weekdays_short' => ['ned.', 'pon.', 'ut.', 'sr.', 'čet.', 'pet.', 'sub.'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.php
new file mode 100644
index 0000000..de20f21
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Glavić
+ * - Milos Sakovic
+ */
+return array_replace_recursive(require __DIR__.'/sr.php', [
+ 'month' => ':count mjesec|:count mjeseca|:count mjeseci',
+ 'week' => ':count nedjelja|:count nedjelje|:count nedjelja',
+ 'second' => ':count sekund|:count sekunde|:count sekundi',
+ 'ago' => 'prije :time',
+ 'from_now' => 'za :time',
+ 'after' => ':time nakon',
+ 'before' => ':time prije',
+ 'week_from_now' => ':count nedjelju|:count nedjelje|:count nedjelja',
+ 'week_ago' => ':count nedjelju|:count nedjelje|:count nedjelja',
+ 'diff_tomorrow' => 'sjutra',
+ 'calendar' => [
+ 'nextDay' => '[sjutra u] LT',
+ 'nextWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[u nedjelju u] LT';
+ case 3:
+ return '[u srijedu u] LT';
+ case 6:
+ return '[u subotu u] LT';
+ default:
+ return '[u] dddd [u] LT';
+ }
+ },
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ return '[prošle nedjelje u] LT';
+ case 1:
+ return '[prošle nedjelje u] LT';
+ case 2:
+ return '[prošlog utorka u] LT';
+ case 3:
+ return '[prošle srijede u] LT';
+ case 4:
+ return '[prošlog četvrtka u] LT';
+ case 5:
+ return '[prošlog petka u] LT';
+ default:
+ return '[prošle subote u] LT';
+ }
+ },
+ ],
+ 'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
+ 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_XK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_XK.php
new file mode 100644
index 0000000..ba7cc09
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_XK.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/sr_Latn_BA.php', [
+ 'weekdays' => ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php
new file mode 100644
index 0000000..b668ee1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/sr_Latn_ME.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_RS.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_RS.php
new file mode 100644
index 0000000..bc5e04b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_RS.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - sr_YU, sr_CS locale Danilo Segan bug-glibc-locales@gnu.org
+ */
+return require __DIR__.'/sr_Cyrl.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_RS@latin.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_RS@latin.php
new file mode 100644
index 0000000..8ae8c41
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sr_RS@latin.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/sr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ss.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ss.php
new file mode 100644
index 0000000..cd4b919
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ss.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Nicolai Davies
+ */
+return [
+ 'year' => '{1}umnyaka|:count iminyaka',
+ 'month' => '{1}inyanga|:count tinyanga',
+ 'week' => '{1}:count liviki|:count emaviki',
+ 'day' => '{1}lilanga|:count emalanga',
+ 'hour' => '{1}lihora|:count emahora',
+ 'minute' => '{1}umzuzu|:count emizuzu',
+ 'second' => '{1}emizuzwana lomcane|:count mzuzwana',
+ 'ago' => 'wenteka nga :time',
+ 'from_now' => 'nga :time',
+ 'diff_yesterday' => 'Itolo',
+ 'diff_yesterday_regexp' => 'Itolo(?:\\s+nga)?',
+ 'diff_today' => 'Namuhla',
+ 'diff_today_regexp' => 'Namuhla(?:\\s+nga)?',
+ 'diff_tomorrow' => 'Kusasa',
+ 'diff_tomorrow_regexp' => 'Kusasa(?:\\s+nga)?',
+ 'formats' => [
+ 'LT' => 'h:mm A',
+ 'LTS' => 'h:mm:ss A',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm A',
+ 'LLLL' => 'dddd, D MMMM YYYY h:mm A',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Namuhla nga] LT',
+ 'nextDay' => '[Kusasa nga] LT',
+ 'nextWeek' => 'dddd [nga] LT',
+ 'lastDay' => '[Itolo nga] LT',
+ 'lastWeek' => 'dddd [leliphelile] [nga] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ $lastDigit = $number % 10;
+
+ return $number.(
+ (~~($number % 100 / 10) === 1) ? 'e' : (
+ ($lastDigit === 1 || $lastDigit === 2) ? 'a' : 'e'
+ )
+ );
+ },
+ 'meridiem' => function ($hour) {
+ if ($hour < 11) {
+ return 'ekuseni';
+ }
+ if ($hour < 15) {
+ return 'emini';
+ }
+ if ($hour < 19) {
+ return 'entsambama';
+ }
+
+ return 'ebusuku';
+ },
+ 'months' => ['Bhimbidvwane', 'Indlovana', 'Indlov\'lenkhulu', 'Mabasa', 'Inkhwekhweti', 'Inhlaba', 'Kholwane', 'Ingci', 'Inyoni', 'Imphala', 'Lweti', 'Ingongoni'],
+ 'months_short' => ['Bhi', 'Ina', 'Inu', 'Mab', 'Ink', 'Inh', 'Kho', 'Igc', 'Iny', 'Imp', 'Lwe', 'Igo'],
+ 'weekdays' => ['Lisontfo', 'Umsombuluko', 'Lesibili', 'Lesitsatfu', 'Lesine', 'Lesihlanu', 'Umgcibelo'],
+ 'weekdays_short' => ['Lis', 'Umb', 'Lsb', 'Les', 'Lsi', 'Lsh', 'Umg'],
+ 'weekdays_min' => ['Li', 'Us', 'Lb', 'Lt', 'Ls', 'Lh', 'Ug'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ss_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ss_ZA.php
new file mode 100644
index 0000000..48d970a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ss_ZA.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/ss.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/st.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/st.php
new file mode 100644
index 0000000..b065445
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/st.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/st_ZA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/st_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/st_ZA.php
new file mode 100644
index 0000000..5bce7f2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/st_ZA.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Pherekgong', 'Hlakola', 'Tlhakubele', 'Mmese', 'Motsheanong', 'Phupjane', 'Phupu', 'Phato', 'Leotse', 'Mphalane', 'Pudungwana', 'Tshitwe'],
+ 'months_short' => ['Phe', 'Hla', 'TlH', 'Mme', 'Mot', 'Jan', 'Upu', 'Pha', 'Leo', 'Mph', 'Pud', 'Tsh'],
+ 'weekdays' => ['Sontaha', 'Mantaha', 'Labobedi', 'Laboraro', 'Labone', 'Labohlano', 'Moqebelo'],
+ 'weekdays_short' => ['Son', 'Mma', 'Bed', 'Rar', 'Ne', 'Hla', 'Moq'],
+ 'weekdays_min' => ['Son', 'Mma', 'Bed', 'Rar', 'Ne', 'Hla', 'Moq'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'week' => ':count Sontaha', // less reliable
+ 'w' => ':count Sontaha', // less reliable
+ 'a_week' => ':count Sontaha', // less reliable
+
+ 'day' => ':count letsatsi', // less reliable
+ 'd' => ':count letsatsi', // less reliable
+ 'a_day' => ':count letsatsi', // less reliable
+
+ 'hour' => ':count sešupanako', // less reliable
+ 'h' => ':count sešupanako', // less reliable
+ 'a_hour' => ':count sešupanako', // less reliable
+
+ 'minute' => ':count menyane', // less reliable
+ 'min' => ':count menyane', // less reliable
+ 'a_minute' => ':count menyane', // less reliable
+
+ 'second' => ':count thusa', // less reliable
+ 's' => ':count thusa', // less reliable
+ 'a_second' => ':count thusa', // less reliable
+
+ 'year' => ':count selemo',
+ 'y' => ':count selemo',
+ 'a_year' => ':count selemo',
+
+ 'month' => ':count kgwedi',
+ 'm' => ':count kgwedi',
+ 'a_month' => ':count kgwedi',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv.php
new file mode 100644
index 0000000..ca33e1c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Kristoffer Snabb
+ * - JD Isaacks
+ * - Jens Herlevsen
+ * - Nightpine
+ * - Anders Nygren (litemerafrukt)
+ */
+return [
+ 'year' => ':count år',
+ 'a_year' => 'ett år|:count år',
+ 'y' => ':count år',
+ 'month' => ':count månad|:count månader',
+ 'a_month' => 'en månad|:count månader',
+ 'm' => ':count mån',
+ 'week' => ':count vecka|:count veckor',
+ 'a_week' => 'en vecka|:count veckor',
+ 'w' => ':count v',
+ 'day' => ':count dag|:count dagar',
+ 'a_day' => 'en dag|:count dagar',
+ 'd' => ':count dgr',
+ 'hour' => ':count timme|:count timmar',
+ 'a_hour' => 'en timme|:count timmar',
+ 'h' => ':count tim',
+ 'minute' => ':count minut|:count minuter',
+ 'a_minute' => 'en minut|:count minuter',
+ 'min' => ':count min',
+ 'second' => ':count sekund|:count sekunder',
+ 'a_second' => 'några sekunder|:count sekunder',
+ 's' => ':count s',
+ 'ago' => 'för :time sedan',
+ 'from_now' => 'om :time',
+ 'after' => ':time efter',
+ 'before' => ':time före',
+ 'diff_now' => 'nu',
+ 'diff_today' => 'I dag',
+ 'diff_yesterday' => 'i går',
+ 'diff_yesterday_regexp' => 'I går',
+ 'diff_tomorrow' => 'i morgon',
+ 'diff_tomorrow_regexp' => 'I morgon',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY [kl.] HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY [kl.] HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[I dag] LT',
+ 'nextDay' => '[I morgon] LT',
+ 'nextWeek' => '[På] dddd LT',
+ 'lastDay' => '[I går] LT',
+ 'lastWeek' => '[I] dddd[s] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ $lastDigit = $number % 10;
+
+ return $number.(
+ (~~($number % 100 / 10) === 1) ? 'e' : (
+ ($lastDigit === 1 || $lastDigit === 2) ? 'a' : 'e'
+ )
+ );
+ },
+ 'months' => ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december'],
+ 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
+ 'weekdays' => ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag', 'lördag'],
+ 'weekdays_short' => ['sön', 'mån', 'tis', 'ons', 'tors', 'fre', 'lör'],
+ 'weekdays_min' => ['sö', 'må', 'ti', 'on', 'to', 'fr', 'lö'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' och '],
+ 'meridiem' => ['fm', 'em'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv_AX.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv_AX.php
new file mode 100644
index 0000000..56425b4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv_AX.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/sv.php', [
+ 'formats' => [
+ 'L' => 'YYYY-MM-dd',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv_FI.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv_FI.php
new file mode 100644
index 0000000..1b73ecb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv_FI.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/sv.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv_SE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv_SE.php
new file mode 100644
index 0000000..1b73ecb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sv_SE.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/sv.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw.php
new file mode 100644
index 0000000..f8630d5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - leyluj
+ * - Josh Soref
+ * - ryanhart2
+ */
+return [
+ 'year' => 'mwaka :count|miaka :count',
+ 'a_year' => 'mwaka mmoja|miaka :count',
+ 'y' => 'mwaka :count|miaka :count',
+ 'month' => 'mwezi :count|miezi :count',
+ 'a_month' => 'mwezi mmoja|miezi :count',
+ 'm' => 'mwezi :count|miezi :count',
+ 'week' => 'wiki :count',
+ 'a_week' => 'wiki mmoja|wiki :count',
+ 'w' => 'w. :count',
+ 'day' => 'siku :count',
+ 'a_day' => 'siku moja|masiku :count',
+ 'd' => 'si. :count',
+ 'hour' => 'saa :count|masaa :count',
+ 'a_hour' => 'saa limoja|masaa :count',
+ 'h' => 'saa :count|masaa :count',
+ 'minute' => 'dakika :count',
+ 'a_minute' => 'dakika moja|dakika :count',
+ 'min' => 'd. :count',
+ 'second' => 'sekunde :count',
+ 'a_second' => 'hivi punde|sekunde :count',
+ 's' => 'se. :count',
+ 'ago' => 'tokea :time',
+ 'from_now' => ':time baadaye',
+ 'after' => ':time baada',
+ 'before' => ':time kabla',
+ 'diff_now' => 'sasa hivi',
+ 'diff_today' => 'leo',
+ 'diff_today_regexp' => 'leo(?:\\s+saa)?',
+ 'diff_yesterday' => 'jana',
+ 'diff_tomorrow' => 'kesho',
+ 'diff_tomorrow_regexp' => 'kesho(?:\\s+saa)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[leo saa] LT',
+ 'nextDay' => '[kesho saa] LT',
+ 'nextWeek' => '[wiki ijayo] dddd [saat] LT',
+ 'lastDay' => '[jana] LT',
+ 'lastWeek' => '[wiki iliyopita] dddd [saat] LT',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
+ 'weekdays_short' => ['Jpl', 'Jtat', 'Jnne', 'Jtan', 'Alh', 'Ijm', 'Jmos'],
+ 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' na '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_CD.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_CD.php
new file mode 100644
index 0000000..f6927f4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_CD.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/sw.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_KE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_KE.php
new file mode 100644
index 0000000..2ace0db
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_KE.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kamusi Project Martin Benjamin locales@kamusi.org
+ */
+return array_replace_recursive(require __DIR__.'/sw.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
+ 'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
+ 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['asubuhi', 'alasiri'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_TZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_TZ.php
new file mode 100644
index 0000000..fab3cd6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_TZ.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kamusi Project Martin Benjamin locales@kamusi.org
+ */
+return array_replace_recursive(require __DIR__.'/sw.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
+ 'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
+ 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['asubuhi', 'alasiri'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_UG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_UG.php
new file mode 100644
index 0000000..f6927f4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sw_UG.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/sw.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/szl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/szl.php
new file mode 100644
index 0000000..4429c4f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/szl.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/szl_PL.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/szl_PL.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/szl_PL.php
new file mode 100644
index 0000000..4b0b541
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/szl_PL.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - szl_PL locale Przemyslaw Buczkowski libc-alpha@sourceware.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['styczyń', 'luty', 'merc', 'kwjeciyń', 'moj', 'czyrwjyń', 'lipjyń', 'siyrpjyń', 'wrzesiyń', 'październik', 'listopad', 'grudziyń'],
+ 'months_short' => ['sty', 'lut', 'mer', 'kwj', 'moj', 'czy', 'lip', 'siy', 'wrz', 'paź', 'lis', 'gru'],
+ 'weekdays' => ['niydziela', 'pyńdziŏek', 'wtŏrek', 'strzŏda', 'sztwortek', 'pjōntek', 'sobŏta'],
+ 'weekdays_short' => ['niy', 'pyń', 'wtŏ', 'str', 'szt', 'pjō', 'sob'],
+ 'weekdays_min' => ['niy', 'pyń', 'wtŏ', 'str', 'szt', 'pjō', 'sob'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'year' => ':count rok',
+ 'y' => ':count rok',
+ 'a_year' => ':count rok',
+
+ 'month' => ':count mjeśůnc',
+ 'm' => ':count mjeśůnc',
+ 'a_month' => ':count mjeśůnc',
+
+ 'week' => ':count Tydźyń',
+ 'w' => ':count Tydźyń',
+ 'a_week' => ':count Tydźyń',
+
+ 'day' => ':count dźyń',
+ 'd' => ':count dźyń',
+ 'a_day' => ':count dźyń',
+
+ 'hour' => ':count godzina',
+ 'h' => ':count godzina',
+ 'a_hour' => ':count godzina',
+
+ 'minute' => ':count Minuta',
+ 'min' => ':count Minuta',
+ 'a_minute' => ':count Minuta',
+
+ 'second' => ':count Sekůnda',
+ 's' => ':count Sekůnda',
+ 'a_second' => ':count Sekůnda',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta.php
new file mode 100644
index 0000000..c1d89cb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - François B
+ * - JD Isaacks
+ * - Satheez
+ */
+return [
+ 'year' => ':count வருடம்|:count ஆண்டுகள்',
+ 'a_year' => 'ஒரு வருடம்|:count ஆண்டுகள்',
+ 'y' => ':count வருட.|:count ஆண்.',
+ 'month' => ':count மாதம்|:count மாதங்கள்',
+ 'a_month' => 'ஒரு மாதம்|:count மாதங்கள்',
+ 'm' => ':count மாத.',
+ 'week' => ':count வாரம்|:count வாரங்கள்',
+ 'a_week' => 'ஒரு வாரம்|:count வாரங்கள்',
+ 'w' => ':count வார.',
+ 'day' => ':count நாள்|:count நாட்கள்',
+ 'a_day' => 'ஒரு நாள்|:count நாட்கள்',
+ 'd' => ':count நாள்|:count நாட்.',
+ 'hour' => ':count மணி நேரம்|:count மணி நேரம்',
+ 'a_hour' => 'ஒரு மணி நேரம்|:count மணி நேரம்',
+ 'h' => ':count மணி.',
+ 'minute' => ':count நிமிடம்|:count நிமிடங்கள்',
+ 'a_minute' => 'ஒரு நிமிடம்|:count நிமிடங்கள்',
+ 'min' => ':count நிமி.',
+ 'second' => ':count சில விநாடிகள்|:count விநாடிகள்',
+ 'a_second' => 'ஒரு சில விநாடிகள்|:count விநாடிகள்',
+ 's' => ':count விநா.',
+ 'ago' => ':time முன்',
+ 'from_now' => ':time இல்',
+ 'before' => ':time முன்',
+ 'after' => ':time பின்',
+ 'diff_now' => 'இப்போது',
+ 'diff_today' => 'இன்று',
+ 'diff_yesterday' => 'நேற்று',
+ 'diff_tomorrow' => 'நாளை',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[இன்று] LT',
+ 'nextDay' => '[நாளை] LT',
+ 'nextWeek' => 'dddd, LT',
+ 'lastDay' => '[நேற்று] LT',
+ 'lastWeek' => '[கடந்த வாரம்] dddd, LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numberவது',
+ 'meridiem' => function ($hour) {
+ if ($hour < 2) {
+ return ' யாமம்';
+ }
+ if ($hour < 6) {
+ return ' வைகறை';
+ }
+ if ($hour < 10) {
+ return ' காலை';
+ }
+ if ($hour < 14) {
+ return ' நண்பகல்';
+ }
+ if ($hour < 18) {
+ return ' எற்பாடு';
+ }
+ if ($hour < 22) {
+ return ' மாலை';
+ }
+
+ return ' யாமம்';
+ },
+ 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டெம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
+ 'months_short' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டெம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
+ 'weekdays' => ['ஞாயிற்றுக்கிழமை', 'திங்கட்கிழமை', 'செவ்வாய்கிழமை', 'புதன்கிழமை', 'வியாழக்கிழமை', 'வெள்ளிக்கிழமை', 'சனிக்கிழமை'],
+ 'weekdays_short' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
+ 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' மற்றும் '],
+ 'weekend' => [0, 0],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_IN.php
new file mode 100644
index 0000000..492d4c5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_IN.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ta.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
+ 'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'],
+ 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
+ 'weekdays_short' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
+ 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['காலை', 'மாலை'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_LK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_LK.php
new file mode 100644
index 0000000..8e2afbf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_LK.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - J.Yogaraj 94-777-315206 yogaraj.ubuntu@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/ta.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
+ 'months_short' => ['ஜன', 'பிப்', 'மார்', 'ஏப்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக', 'செப்', 'அக்', 'நவ', 'டிச'],
+ 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
+ 'weekdays_short' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
+ 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['காலை', 'மாலை'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_MY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_MY.php
new file mode 100644
index 0000000..291d6c8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_MY.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ta.php', [
+ 'formats' => [
+ 'LT' => 'a h:mm',
+ 'LTS' => 'a h:mm:ss',
+ 'L' => 'D/M/yy',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM, YYYY, a h:mm',
+ 'LLLL' => 'dddd, D MMMM, YYYY, a h:mm',
+ ],
+ 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
+ 'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'],
+ 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
+ 'weekdays_short' => ['ஞாயி.', 'திங்.', 'செவ்.', 'புத.', 'வியா.', 'வெள்.', 'சனி'],
+ 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
+ 'first_day_of_week' => 1,
+ 'meridiem' => ['மு.ப', 'பி.ப'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_SG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_SG.php
new file mode 100644
index 0000000..fe1cc06
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ta_SG.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ta.php', [
+ 'formats' => [
+ 'LT' => 'a h:mm',
+ 'LTS' => 'a h:mm:ss',
+ 'L' => 'D/M/yy',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM, YYYY, a h:mm',
+ 'LLLL' => 'dddd, D MMMM, YYYY, a h:mm',
+ ],
+ 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
+ 'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'],
+ 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
+ 'weekdays_short' => ['ஞாயி.', 'திங்.', 'செவ்.', 'புத.', 'வியா.', 'வெள்.', 'சனி'],
+ 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
+ 'meridiem' => ['மு.ப', 'பி.ப'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tcy.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tcy.php
new file mode 100644
index 0000000..2eb9905
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tcy.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/tcy_IN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tcy_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tcy_IN.php
new file mode 100644
index 0000000..2ff20e0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tcy_IN.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IndLinux.org, Samsung Electronics Co., Ltd. alexey.merzlyakov@samsung.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['ಜನವರಿ', 'ಫೆಬ್ರುವರಿ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್', 'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್', 'ಡಿಸೆಂಬರ್'],
+ 'months_short' => ['ಜ', 'ಫೆ', 'ಮಾ', 'ಏ', 'ಮೇ', 'ಜೂ', 'ಜು', 'ಆ', 'ಸೆ', 'ಅ', 'ನ', 'ಡಿ'],
+ 'weekdays' => ['ಐಥಾರ', 'ಸೋಮಾರ', 'ಅಂಗರೆ', 'ಬುಧಾರ', 'ಗುರುವಾರ', 'ಶುಕ್ರರ', 'ಶನಿವಾರ'],
+ 'weekdays_short' => ['ಐ', 'ಸೋ', 'ಅಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'],
+ 'weekdays_min' => ['ಐ', 'ಸೋ', 'ಅಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ಕಾಂಡೆ', 'ಬಯ್ಯ'],
+
+ 'year' => ':count ನೀರ್', // less reliable
+ 'y' => ':count ನೀರ್', // less reliable
+ 'a_year' => ':count ನೀರ್', // less reliable
+
+ 'month' => ':count ಮೀನ್', // less reliable
+ 'm' => ':count ಮೀನ್', // less reliable
+ 'a_month' => ':count ಮೀನ್', // less reliable
+
+ 'day' => ':count ಸುಗ್ಗಿ', // less reliable
+ 'd' => ':count ಸುಗ್ಗಿ', // less reliable
+ 'a_day' => ':count ಸುಗ್ಗಿ', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/te.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/te.php
new file mode 100644
index 0000000..ac38218
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/te.php
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kunal Marwaha
+ * - Josh Soref
+ * - François B
+ * - kc
+ */
+return [
+ 'year' => ':count సంవత్సరం|:count సంవత్సరాలు',
+ 'a_year' => 'ఒక సంవత్సరం|:count సంవత్సరాలు',
+ 'y' => ':count సం.',
+ 'month' => ':count నెల|:count నెలలు',
+ 'a_month' => 'ఒక నెల|:count నెలలు',
+ 'm' => ':count నెల|:count నెల.',
+ 'week' => ':count వారం|:count వారాలు',
+ 'a_week' => 'ఒక వారం|:count వారాలు',
+ 'w' => ':count వార.|:count వారా.',
+ 'day' => ':count రోజు|:count రోజులు',
+ 'a_day' => 'ఒక రోజు|:count రోజులు',
+ 'd' => ':count రోజు|:count రోజు.',
+ 'hour' => ':count గంట|:count గంటలు',
+ 'a_hour' => 'ఒక గంట|:count గంటలు',
+ 'h' => ':count గం.',
+ 'minute' => ':count నిమిషం|:count నిమిషాలు',
+ 'a_minute' => 'ఒక నిమిషం|:count నిమిషాలు',
+ 'min' => ':count నిమి.',
+ 'second' => ':count సెకను|:count సెకన్లు',
+ 'a_second' => 'కొన్ని క్షణాలు|:count సెకన్లు',
+ 's' => ':count సెక.',
+ 'ago' => ':time క్రితం',
+ 'from_now' => ':time లో',
+ 'diff_now' => 'ప్రస్తుతం',
+ 'diff_today' => 'నేడు',
+ 'diff_yesterday' => 'నిన్న',
+ 'diff_tomorrow' => 'రేపు',
+ 'formats' => [
+ 'LT' => 'A h:mm',
+ 'LTS' => 'A h:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, A h:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY, A h:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[నేడు] LT',
+ 'nextDay' => '[రేపు] LT',
+ 'nextWeek' => 'dddd, LT',
+ 'lastDay' => '[నిన్న] LT',
+ 'lastWeek' => '[గత] dddd, LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numberవ',
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'రాత్రి';
+ }
+ if ($hour < 10) {
+ return 'ఉదయం';
+ }
+ if ($hour < 17) {
+ return 'మధ్యాహ్నం';
+ }
+ if ($hour < 20) {
+ return 'సాయంత్రం';
+ }
+
+ return ' రాత్రి';
+ },
+ 'months' => ['జనవరి', 'ఫిబ్రవరి', 'మార్చి', 'ఏప్రిల్', 'మే', 'జూన్', 'జూలై', 'ఆగస్టు', 'సెప్టెంబర్', 'అక్టోబర్', 'నవంబర్', 'డిసెంబర్'],
+ 'months_short' => ['జన.', 'ఫిబ్ర.', 'మార్చి', 'ఏప్రి.', 'మే', 'జూన్', 'జూలై', 'ఆగ.', 'సెప్.', 'అక్టో.', 'నవ.', 'డిసె.'],
+ 'weekdays' => ['ఆదివారం', 'సోమవారం', 'మంగళవారం', 'బుధవారం', 'గురువారం', 'శుక్రవారం', 'శనివారం'],
+ 'weekdays_short' => ['ఆది', 'సోమ', 'మంగళ', 'బుధ', 'గురు', 'శుక్ర', 'శని'],
+ 'weekdays_min' => ['ఆ', 'సో', 'మం', 'బు', 'గు', 'శు', 'శ'],
+ 'list' => ', ',
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'weekend' => [0, 0],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/te_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/te_IN.php
new file mode 100644
index 0000000..6f81c40
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/te_IN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/te.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/teo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/teo.php
new file mode 100644
index 0000000..950235e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/teo.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ta.php', [
+ 'meridiem' => ['Taparachu', 'Ebongi'],
+ 'weekdays' => ['Nakaejuma', 'Nakaebarasa', 'Nakaare', 'Nakauni', 'Nakaung’on', 'Nakakany', 'Nakasabiti'],
+ 'weekdays_short' => ['Jum', 'Bar', 'Aar', 'Uni', 'Ung', 'Kan', 'Sab'],
+ 'weekdays_min' => ['Jum', 'Bar', 'Aar', 'Uni', 'Ung', 'Kan', 'Sab'],
+ 'months' => ['Orara', 'Omuk', 'Okwamg’', 'Odung’el', 'Omaruk', 'Omodok’king’ol', 'Ojola', 'Opedel', 'Osokosokoma', 'Otibar', 'Olabor', 'Opoo'],
+ 'months_short' => ['Rar', 'Muk', 'Kwa', 'Dun', 'Mar', 'Mod', 'Jol', 'Ped', 'Sok', 'Tib', 'Lab', 'Poo'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/teo_KE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/teo_KE.php
new file mode 100644
index 0000000..024d272
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/teo_KE.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/teo.php', [
+ 'first_day_of_week' => 0,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tet.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tet.php
new file mode 100644
index 0000000..d0544d4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tet.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Joshua Brooks
+ * - François B
+ */
+return [
+ 'year' => 'tinan :count',
+ 'a_year' => '{1}tinan ida|tinan :count',
+ 'month' => 'fulan :count',
+ 'a_month' => '{1}fulan ida|fulan :count',
+ 'week' => 'semana :count',
+ 'a_week' => '{1}semana ida|semana :count',
+ 'day' => 'loron :count',
+ 'a_day' => '{1}loron ida|loron :count',
+ 'hour' => 'oras :count',
+ 'a_hour' => '{1}oras ida|oras :count',
+ 'minute' => 'minutu :count',
+ 'a_minute' => '{1}minutu ida|minutu :count',
+ 'second' => 'segundu :count',
+ 'a_second' => '{1}segundu balun|segundu :count',
+ 'ago' => ':time liuba',
+ 'from_now' => 'iha :time',
+ 'diff_yesterday' => 'Horiseik',
+ 'diff_yesterday_regexp' => 'Horiseik(?:\\s+iha)?',
+ 'diff_today' => 'Ohin',
+ 'diff_today_regexp' => 'Ohin(?:\\s+iha)?',
+ 'diff_tomorrow' => 'Aban',
+ 'diff_tomorrow_regexp' => 'Aban(?:\\s+iha)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Ohin iha] LT',
+ 'nextDay' => '[Aban iha] LT',
+ 'nextWeek' => 'dddd [iha] LT',
+ 'lastDay' => '[Horiseik iha] LT',
+ 'lastWeek' => 'dddd [semana kotuk] [iha] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':numberº',
+ 'months' => ['Janeiru', 'Fevereiru', 'Marsu', 'Abril', 'Maiu', 'Juñu', 'Jullu', 'Agustu', 'Setembru', 'Outubru', 'Novembru', 'Dezembru'],
+ 'months_short' => ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
+ 'weekdays' => ['Domingu', 'Segunda', 'Tersa', 'Kuarta', 'Kinta', 'Sesta', 'Sabadu'],
+ 'weekdays_short' => ['Dom', 'Seg', 'Ters', 'Kua', 'Kint', 'Sest', 'Sab'],
+ 'weekdays_min' => ['Do', 'Seg', 'Te', 'Ku', 'Ki', 'Ses', 'Sa'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tg.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tg.php
new file mode 100644
index 0000000..b7df893
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tg.php
@@ -0,0 +1,104 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Orif N. Jr
+ */
+return [
+ 'year' => '{1}як сол|:count сол',
+ 'month' => '{1}як моҳ|:count моҳ',
+ 'week' => '{1}як ҳафта|:count ҳафта',
+ 'day' => '{1}як рӯз|:count рӯз',
+ 'hour' => '{1}як соат|:count соат',
+ 'minute' => '{1}як дақиқа|:count дақиқа',
+ 'second' => '{1}якчанд сония|:count сония',
+ 'ago' => ':time пеш',
+ 'from_now' => 'баъди :time',
+ 'diff_today' => 'Имрӯз',
+ 'diff_yesterday' => 'Дирӯз',
+ 'diff_yesterday_regexp' => 'Дирӯз(?:\\s+соати)?',
+ 'diff_tomorrow' => 'Пагоҳ',
+ 'diff_tomorrow_regexp' => 'Пагоҳ(?:\\s+соати)?',
+ 'diff_today_regexp' => 'Имрӯз(?:\\s+соати)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Имрӯз соати] LT',
+ 'nextDay' => '[Пагоҳ соати] LT',
+ 'nextWeek' => 'dddd[и] [ҳафтаи оянда соати] LT',
+ 'lastDay' => '[Дирӯз соати] LT',
+ 'lastWeek' => 'dddd[и] [ҳафтаи гузашта соати] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number) {
+ if ($number === 0) { // special case for zero
+ return "$number-ıncı";
+ }
+
+ static $suffixes = [
+ 0 => '-ум',
+ 1 => '-ум',
+ 2 => '-юм',
+ 3 => '-юм',
+ 4 => '-ум',
+ 5 => '-ум',
+ 6 => '-ум',
+ 7 => '-ум',
+ 8 => '-ум',
+ 9 => '-ум',
+ 10 => '-ум',
+ 12 => '-ум',
+ 13 => '-ум',
+ 20 => '-ум',
+ 30 => '-юм',
+ 40 => '-ум',
+ 50 => '-ум',
+ 60 => '-ум',
+ 70 => '-ум',
+ 80 => '-ум',
+ 90 => '-ум',
+ 100 => '-ум',
+ ];
+
+ return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
+ },
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'шаб';
+ }
+ if ($hour < 11) {
+ return 'субҳ';
+ }
+ if ($hour < 16) {
+ return 'рӯз';
+ }
+ if ($hour < 19) {
+ return 'бегоҳ';
+ }
+
+ return 'шаб';
+ },
+ 'months' => ['январ', 'феврал', 'март', 'апрел', 'май', 'июн', 'июл', 'август', 'сентябр', 'октябр', 'ноябр', 'декабр'],
+ 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
+ 'weekdays' => ['якшанбе', 'душанбе', 'сешанбе', 'чоршанбе', 'панҷшанбе', 'ҷумъа', 'шанбе'],
+ 'weekdays_short' => ['яшб', 'дшб', 'сшб', 'чшб', 'пшб', 'ҷум', 'шнб'],
+ 'weekdays_min' => ['яш', 'дш', 'сш', 'чш', 'пш', 'ҷм', 'шб'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' ва '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tg_TJ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tg_TJ.php
new file mode 100644
index 0000000..c6591e3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tg_TJ.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/tg.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/th.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/th.php
new file mode 100644
index 0000000..6397f6e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/th.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Nate Whittaker
+ * - John MacAslan
+ * - Chanintorn Asavavichairoj
+ * - JD Isaacks
+ * - ROKAISAKKON
+ * - RO'KAISAKKON
+ * - Andreas Möller
+ * - nithisa
+ */
+return [
+ 'year' => ':count ปี',
+ 'y' => ':count ปี',
+ 'month' => ':count เดือน',
+ 'm' => ':count เดือน',
+ 'week' => ':count สัปดาห์',
+ 'w' => ':count สัปดาห์',
+ 'day' => ':count วัน',
+ 'd' => ':count วัน',
+ 'hour' => ':count ชั่วโมง',
+ 'h' => ':count ชั่วโมง',
+ 'minute' => ':count นาที',
+ 'min' => ':count นาที',
+ 'second' => ':count วินาที',
+ 'a_second' => '{1}ไม่กี่วินาที|]1,Inf[:count วินาที',
+ 's' => ':count วินาที',
+ 'ago' => ':timeที่แล้ว',
+ 'from_now' => 'อีก :time',
+ 'after' => ':timeหลังจากนี้',
+ 'before' => ':timeก่อน',
+ 'diff_now' => 'ขณะนี้',
+ 'diff_today' => 'วันนี้',
+ 'diff_today_regexp' => 'วันนี้(?:\\s+เวลา)?',
+ 'diff_yesterday' => 'เมื่อวาน',
+ 'diff_yesterday_regexp' => 'เมื่อวานนี้(?:\\s+เวลา)?',
+ 'diff_tomorrow' => 'พรุ่งนี้',
+ 'diff_tomorrow_regexp' => 'พรุ่งนี้(?:\\s+เวลา)?',
+ 'formats' => [
+ 'LT' => 'H:mm',
+ 'LTS' => 'H:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY เวลา H:mm',
+ 'LLLL' => 'วันddddที่ D MMMM YYYY เวลา H:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[วันนี้ เวลา] LT',
+ 'nextDay' => '[พรุ่งนี้ เวลา] LT',
+ 'nextWeek' => 'dddd[หน้า เวลา] LT',
+ 'lastDay' => '[เมื่อวานนี้ เวลา] LT',
+ 'lastWeek' => '[วัน]dddd[ที่แล้ว เวลา] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['ก่อนเที่ยง', 'หลังเที่ยง'],
+ 'months' => ['มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'],
+ 'months_short' => ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.'],
+ 'weekdays' => ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัสบดี', 'ศุกร์', 'เสาร์'],
+ 'weekdays_short' => ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัส', 'ศุกร์', 'เสาร์'],
+ 'weekdays_min' => ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'],
+ 'list' => [', ', ' และ '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/th_TH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/th_TH.php
new file mode 100644
index 0000000..f11dc1b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/th_TH.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/th.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/the.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/the.php
new file mode 100644
index 0000000..85f8333
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/the.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/the_NP.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/the_NP.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/the_NP.php
new file mode 100644
index 0000000..34da162
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/the_NP.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Chitwanix OS Development info@chitwanix.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'dddd DD MMM YYYY',
+ ],
+ 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
+ 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
+ 'weekdays' => ['आइतबार', 'सोमबार', 'मंगलबार', 'बुधबार', 'बिहिबार', 'शुक्रबार', 'शनिबार'],
+ 'weekdays_short' => ['आइत', 'सोम', 'मंगल', 'बुध', 'बिहि', 'शुक्र', 'शनि'],
+ 'weekdays_min' => ['आइत', 'सोम', 'मंगल', 'बुध', 'बिहि', 'शुक्र', 'शनि'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ti.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ti.php
new file mode 100644
index 0000000..ffd3236
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ti.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ti_ER.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ti_ER.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ti_ER.php
new file mode 100644
index 0000000..310c51c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ti_ER.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['ጥሪ', 'ለካቲት', 'መጋቢት', 'ሚያዝያ', 'ግንቦት', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከረም', 'ጥቅምቲ', 'ሕዳር', 'ታሕሳስ'],
+ 'months_short' => ['ጥሪ ', 'ለካቲ', 'መጋቢ', 'ሚያዝ', 'ግንቦ', 'ሰነ ', 'ሓምለ', 'ነሓሰ', 'መስከ', 'ጥቅም', 'ሕዳር', 'ታሕሳ'],
+ 'weekdays' => ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
+ 'weekdays_short' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
+ 'weekdays_min' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ንጉሆ ሰዓተ', 'ድሕር ሰዓት'],
+
+ 'year' => ':count ዓመት',
+ 'y' => ':count ዓመት',
+ 'a_year' => ':count ዓመት',
+
+ 'month' => 'ወርሒ :count',
+ 'm' => 'ወርሒ :count',
+ 'a_month' => 'ወርሒ :count',
+
+ 'week' => ':count ሰሙን',
+ 'w' => ':count ሰሙን',
+ 'a_week' => ':count ሰሙን',
+
+ 'day' => ':count መዓልቲ',
+ 'd' => ':count መዓልቲ',
+ 'a_day' => ':count መዓልቲ',
+
+ 'hour' => ':count ሰዓት',
+ 'h' => ':count ሰዓት',
+ 'a_hour' => ':count ሰዓት',
+
+ 'minute' => ':count ደቒቕ',
+ 'min' => ':count ደቒቕ',
+ 'a_minute' => ':count ደቒቕ',
+
+ 'second' => ':count ሰከንድ',
+ 's' => ':count ሰከንድ',
+ 'a_second' => ':count ሰከንድ',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ti_ET.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ti_ET.php
new file mode 100644
index 0000000..024217f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ti_ET.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'],
+ 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
+ 'weekdays' => ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
+ 'weekdays_short' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
+ 'weekdays_min' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ንጉሆ ሰዓተ', 'ድሕር ሰዓት'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tig.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tig.php
new file mode 100644
index 0000000..186fe71
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tig.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/tig_ER.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tig_ER.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tig_ER.php
new file mode 100644
index 0000000..46887b0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tig_ER.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['ጥሪ', 'ለካቲት', 'መጋቢት', 'ሚያዝያ', 'ግንቦት', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከረም', 'ጥቅምቲ', 'ሕዳር', 'ታሕሳስ'],
+ 'months_short' => ['ጥሪ ', 'ለካቲ', 'መጋቢ', 'ሚያዝ', 'ግንቦ', 'ሰነ ', 'ሓምለ', 'ነሓሰ', 'መስከ', 'ጥቅም', 'ሕዳር', 'ታሕሳ'],
+ 'weekdays' => ['ሰንበት ዓባይ', 'ሰኖ', 'ታላሸኖ', 'ኣረርባዓ', 'ከሚሽ', 'ጅምዓት', 'ሰንበት ንኢሽ'],
+ 'weekdays_short' => ['ሰ//ዓ', 'ሰኖ ', 'ታላሸ', 'ኣረር', 'ከሚሽ', 'ጅምዓ', 'ሰ//ን'],
+ 'weekdays_min' => ['ሰ//ዓ', 'ሰኖ ', 'ታላሸ', 'ኣረር', 'ከሚሽ', 'ጅምዓ', 'ሰ//ን'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ቀደም ሰር ምዕል', 'ሓቆ ሰር ምዕል'],
+
+ 'year' => ':count ማይ', // less reliable
+ 'y' => ':count ማይ', // less reliable
+ 'a_year' => ':count ማይ', // less reliable
+
+ 'month' => ':count ሸምሽ', // less reliable
+ 'm' => ':count ሸምሽ', // less reliable
+ 'a_month' => ':count ሸምሽ', // less reliable
+
+ 'week' => ':count ሰቡዕ', // less reliable
+ 'w' => ':count ሰቡዕ', // less reliable
+ 'a_week' => ':count ሰቡዕ', // less reliable
+
+ 'day' => ':count ዎሮ', // less reliable
+ 'd' => ':count ዎሮ', // less reliable
+ 'a_day' => ':count ዎሮ', // less reliable
+
+ 'hour' => ':count ሰዓት', // less reliable
+ 'h' => ':count ሰዓት', // less reliable
+ 'a_hour' => ':count ሰዓት', // less reliable
+
+ 'minute' => ':count ካልኣይት', // less reliable
+ 'min' => ':count ካልኣይት', // less reliable
+ 'a_minute' => ':count ካልኣይት', // less reliable
+
+ 'second' => ':count ካልኣይ',
+ 's' => ':count ካልኣይ',
+ 'a_second' => ':count ካልኣይ',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tk.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tk.php
new file mode 100644
index 0000000..d8f7d19
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tk.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/tk_TM.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tk_TM.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tk_TM.php
new file mode 100644
index 0000000..f949a43
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tk_TM.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Authors:
+ * - Ghorban M. Tavakoly Pablo Saratxaga & Ghorban M. Tavakoly pablo@walon.org & gmt314@yahoo.com
+ * - SuperManPHP
+ * - Maksat Meredow (isadma)
+ */
+$transformDiff = function ($input) {
+ return strtr($input, [
+ 'sekunt' => 'sekunt',
+ 'hepde' => 'hepde',
+ ]);
+};
+
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['Ýanwar', 'Fewral', 'Mart', 'Aprel', 'Maý', 'Iýun', 'Iýul', 'Awgust', 'Sentýabr', 'Oktýabr', 'Noýabr', 'Dekabr'],
+ 'months_short' => ['Ýan', 'Few', 'Mar', 'Apr', 'Maý', 'Iýn', 'Iýl', 'Awg', 'Sen', 'Okt', 'Noý', 'Dek'],
+ 'weekdays' => ['Duşenbe', 'Sişenbe', 'Çarşenbe', 'Penşenbe', 'Anna', 'Şenbe', 'Ýekşenbe'],
+ 'weekdays_short' => ['Duş', 'Siş', 'Çar', 'Pen', 'Ann', 'Şen', 'Ýek'],
+ 'weekdays_min' => ['Du', 'Si', 'Ça', 'Pe', 'An', 'Şe', 'Ýe'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count ýyl',
+ 'y' => ':count ýyl',
+ 'a_year' => ':count ýyl',
+
+ 'month' => ':count aý',
+ 'm' => ':count aý',
+ 'a_month' => ':count aý',
+
+ 'week' => ':count hepde',
+ 'w' => ':count hepde',
+ 'a_week' => ':count hepde',
+
+ 'day' => ':count gün',
+ 'd' => ':count gün',
+ 'a_day' => ':count gün',
+
+ 'hour' => ':count sagat',
+ 'h' => ':count sagat',
+ 'a_hour' => ':count sagat',
+
+ 'minute' => ':count minut',
+ 'min' => ':count minut',
+ 'a_minute' => ':count minut',
+
+ 'second' => ':count sekunt',
+ 's' => ':count sekunt',
+ 'a_second' => ':count sekunt',
+
+ 'ago' => function ($time) use ($transformDiff) {
+ return $transformDiff($time).' ozal';
+ },
+ 'from_now' => function ($time) use ($transformDiff) {
+ return $transformDiff($time).' soňra';
+ },
+ 'after' => function ($time) use ($transformDiff) {
+ return $transformDiff($time).' soň';
+ },
+ 'before' => function ($time) use ($transformDiff) {
+ return $transformDiff($time).' öň';
+ },
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tl.php
new file mode 100644
index 0000000..410a266
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tl.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return [
+ 'year' => ':count taon',
+ 'a_year' => '{1}isang taon|:count taon',
+ 'month' => ':count buwan',
+ 'a_month' => '{1}isang buwan|:count buwan',
+ 'week' => ':count linggo',
+ 'a_week' => '{1}isang linggo|:count linggo',
+ 'day' => ':count araw',
+ 'a_day' => '{1}isang araw|:count araw',
+ 'hour' => ':count oras',
+ 'a_hour' => '{1}isang oras|:count oras',
+ 'minute' => ':count minuto',
+ 'a_minute' => '{1}isang minuto|:count minuto',
+ 'min' => ':count min.',
+ 'second' => ':count segundo',
+ 'a_second' => '{1}ilang segundo|:count segundo',
+ 's' => ':count seg.',
+ 'ago' => ':time ang nakalipas',
+ 'from_now' => 'sa loob ng :time',
+ 'diff_now' => 'ngayon',
+ 'diff_today' => 'ngayong',
+ 'diff_today_regexp' => 'ngayong(?:\\s+araw)?',
+ 'diff_yesterday' => 'kahapon',
+ 'diff_tomorrow' => 'bukas',
+ 'diff_tomorrow_regexp' => 'Bukas(?:\\s+ng)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'MM/D/YYYY',
+ 'LL' => 'MMMM D, YYYY',
+ 'LLL' => 'MMMM D, YYYY HH:mm',
+ 'LLLL' => 'dddd, MMMM DD, YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => 'LT [ngayong araw]',
+ 'nextDay' => '[Bukas ng] LT',
+ 'nextWeek' => 'LT [sa susunod na] dddd',
+ 'lastDay' => 'LT [kahapon]',
+ 'lastWeek' => 'LT [noong nakaraang] dddd',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
+ 'months_short' => ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set', 'Okt', 'Nob', 'Dis'],
+ 'weekdays' => ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes', 'Biyernes', 'Sabado'],
+ 'weekdays_short' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
+ 'weekdays_min' => ['Li', 'Lu', 'Ma', 'Mi', 'Hu', 'Bi', 'Sab'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' at '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tl_PH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tl_PH.php
new file mode 100644
index 0000000..95f508c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tl_PH.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Ian De La Cruz
+ * - JD Isaacks
+ */
+return require __DIR__.'/tl.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tlh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tlh.php
new file mode 100644
index 0000000..fbf9e6f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tlh.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Serhan Apaydın
+ * - Dominika
+ */
+return [
+ 'year' => '{1}wa’ DIS|:count DIS',
+ 'month' => '{1}wa’ jar|:count jar',
+ 'week' => '{1}wa’ hogh|:count hogh',
+ 'day' => '{1}wa’ jaj|:count jaj',
+ 'hour' => '{1}wa’ rep|:count rep',
+ 'minute' => '{1}wa’ tup|:count tup',
+ 'second' => '{1}puS lup|:count lup',
+ 'ago' => function ($time) {
+ $output = strtr($time, [
+ 'jaj' => 'Hu’',
+ 'jar' => 'wen',
+ 'DIS' => 'ben',
+ ]);
+
+ return $output === $time ? "$time ret" : $output;
+ },
+ 'from_now' => function ($time) {
+ $output = strtr($time, [
+ 'jaj' => 'leS',
+ 'jar' => 'waQ',
+ 'DIS' => 'nem',
+ ]);
+
+ return $output === $time ? "$time pIq" : $output;
+ },
+ 'diff_yesterday' => 'wa’Hu’',
+ 'diff_today' => 'DaHjaj',
+ 'diff_tomorrow' => 'wa’leS',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[DaHjaj] LT',
+ 'nextDay' => '[wa’leS] LT',
+ 'nextWeek' => 'LLL',
+ 'lastDay' => '[wa’Hu’] LT',
+ 'lastWeek' => 'LLL',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => ':number.',
+ 'months' => ['tera’ jar wa’', 'tera’ jar cha’', 'tera’ jar wej', 'tera’ jar loS', 'tera’ jar vagh', 'tera’ jar jav', 'tera’ jar Soch', 'tera’ jar chorgh', 'tera’ jar Hut', 'tera’ jar wa’maH', 'tera’ jar wa’maH wa’', 'tera’ jar wa’maH cha’'],
+ 'months_short' => ['jar wa’', 'jar cha’', 'jar wej', 'jar loS', 'jar vagh', 'jar jav', 'jar Soch', 'jar chorgh', 'jar Hut', 'jar wa’maH', 'jar wa’maH wa’', 'jar wa’maH cha’'],
+ 'weekdays' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'],
+ 'weekdays_short' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'],
+ 'weekdays_min' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' ’ej '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tn.php
new file mode 100644
index 0000000..f29bdf6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tn.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/tn_ZA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tn_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tn_ZA.php
new file mode 100644
index 0000000..aada7db
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tn_ZA.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Ferikgong', 'Tlhakole', 'Mopitlwe', 'Moranang', 'Motsheganong', 'Seetebosigo', 'Phukwi', 'Phatwe', 'Lwetse', 'Diphalane', 'Ngwanatsele', 'Sedimonthole'],
+ 'months_short' => ['Fer', 'Tlh', 'Mop', 'Mor', 'Mot', 'See', 'Phu', 'Pha', 'Lwe', 'Dip', 'Ngw', 'Sed'],
+ 'weekdays' => ['laTshipi', 'Mosupologo', 'Labobedi', 'Laboraro', 'Labone', 'Labotlhano', 'Lamatlhatso'],
+ 'weekdays_short' => ['Tsh', 'Mos', 'Bed', 'Rar', 'Ne', 'Tlh', 'Mat'],
+ 'weekdays_min' => ['Tsh', 'Mos', 'Bed', 'Rar', 'Ne', 'Tlh', 'Mat'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => 'dingwaga di le :count',
+ 'y' => 'dingwaga di le :count',
+ 'a_year' => 'dingwaga di le :count',
+
+ 'month' => 'dikgwedi di le :count',
+ 'm' => 'dikgwedi di le :count',
+ 'a_month' => 'dikgwedi di le :count',
+
+ 'week' => 'dibeke di le :count',
+ 'w' => 'dibeke di le :count',
+ 'a_week' => 'dibeke di le :count',
+
+ 'day' => 'malatsi :count',
+ 'd' => 'malatsi :count',
+ 'a_day' => 'malatsi :count',
+
+ 'hour' => 'diura di le :count',
+ 'h' => 'diura di le :count',
+ 'a_hour' => 'diura di le :count',
+
+ 'minute' => 'metsotso e le :count',
+ 'min' => 'metsotso e le :count',
+ 'a_minute' => 'metsotso e le :count',
+
+ 'second' => 'metsotswana e le :count',
+ 's' => 'metsotswana e le :count',
+ 'a_second' => 'metsotswana e le :count',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/to.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/to.php
new file mode 100644
index 0000000..20581bb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/to.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/to_TO.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/to_TO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/to_TO.php
new file mode 100644
index 0000000..335c69a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/to_TO.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - International Components for Unicode akhilesh.k@samsung.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'dddd DD MMM YYYY',
+ ],
+ 'months' => ['Sānuali', 'Fēpueli', 'Maʻasi', 'ʻEpeleli', 'Mē', 'Sune', 'Siulai', 'ʻAokosi', 'Sepitema', 'ʻOkatopa', 'Nōvema', 'Tīsema'],
+ 'months_short' => ['Sān', 'Fēp', 'Maʻa', 'ʻEpe', 'Mē', 'Sun', 'Siu', 'ʻAok', 'Sep', 'ʻOka', 'Nōv', 'Tīs'],
+ 'weekdays' => ['Sāpate', 'Mōnite', 'Tūsite', 'Pulelulu', 'Tuʻapulelulu', 'Falaite', 'Tokonaki'],
+ 'weekdays_short' => ['Sāp', 'Mōn', 'Tūs', 'Pul', 'Tuʻa', 'Fal', 'Tok'],
+ 'weekdays_min' => ['Sāp', 'Mōn', 'Tūs', 'Pul', 'Tuʻa', 'Fal', 'Tok'],
+ 'meridiem' => ['hengihengi', 'efiafi'],
+
+ 'year' => ':count fitu', // less reliable
+ 'y' => ':count fitu', // less reliable
+ 'a_year' => ':count fitu', // less reliable
+
+ 'month' => ':count mahina', // less reliable
+ 'm' => ':count mahina', // less reliable
+ 'a_month' => ':count mahina', // less reliable
+
+ 'week' => ':count Sapate', // less reliable
+ 'w' => ':count Sapate', // less reliable
+ 'a_week' => ':count Sapate', // less reliable
+
+ 'day' => ':count ʻaho', // less reliable
+ 'd' => ':count ʻaho', // less reliable
+ 'a_day' => ':count ʻaho', // less reliable
+
+ 'hour' => ':count houa',
+ 'h' => ':count houa',
+ 'a_hour' => ':count houa',
+
+ 'minute' => ':count miniti',
+ 'min' => ':count miniti',
+ 'a_minute' => ':count miniti',
+
+ 'second' => ':count sekoni',
+ 's' => ':count sekoni',
+ 'a_second' => ':count sekoni',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tpi.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tpi.php
new file mode 100644
index 0000000..7d38dae
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tpi.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/tpi_PG.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tpi_PG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tpi_PG.php
new file mode 100644
index 0000000..5f58c44
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tpi_PG.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Janueri', 'Februeri', 'Mas', 'Epril', 'Me', 'Jun', 'Julai', 'Ogas', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mas', 'Epr', 'Me', 'Jun', 'Jul', 'Oga', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'weekdays' => ['Sande', 'Mande', 'Tunde', 'Trinde', 'Fonde', 'Fraide', 'Sarere'],
+ 'weekdays_short' => ['San', 'Man', 'Tun', 'Tri', 'Fon', 'Fra', 'Sar'],
+ 'weekdays_min' => ['San', 'Man', 'Tun', 'Tri', 'Fon', 'Fra', 'Sar'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['biknait', 'apinun'],
+
+ 'year' => 'yia :count',
+ 'y' => 'yia :count',
+ 'a_year' => 'yia :count',
+
+ 'month' => ':count mun',
+ 'm' => ':count mun',
+ 'a_month' => ':count mun',
+
+ 'week' => ':count wik',
+ 'w' => ':count wik',
+ 'a_week' => ':count wik',
+
+ 'day' => ':count de',
+ 'd' => ':count de',
+ 'a_day' => ':count de',
+
+ 'hour' => ':count aua',
+ 'h' => ':count aua',
+ 'a_hour' => ':count aua',
+
+ 'minute' => ':count minit',
+ 'min' => ':count minit',
+ 'a_minute' => ':count minit',
+
+ 'second' => ':count namba tu',
+ 's' => ':count namba tu',
+ 'a_second' => ':count namba tu',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tr.php
new file mode 100644
index 0000000..f5d9f4c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tr.php
@@ -0,0 +1,121 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - Alan Agius
+ * - Erhan Gundogan
+ * - François B
+ * - JD Isaacks
+ * - Murat Yüksel
+ * - Baran Şengül
+ * - Selami (selamialtin)
+ * - TeomanBey
+ */
+return [
+ 'year' => ':count yıl',
+ 'a_year' => '{1}bir yıl|]1,Inf[:count yıl',
+ 'y' => ':county',
+ 'month' => ':count ay',
+ 'a_month' => '{1}bir ay|]1,Inf[:count ay',
+ 'm' => ':countay',
+ 'week' => ':count hafta',
+ 'a_week' => '{1}bir hafta|]1,Inf[:count hafta',
+ 'w' => ':counth',
+ 'day' => ':count gün',
+ 'a_day' => '{1}bir gün|]1,Inf[:count gün',
+ 'd' => ':countg',
+ 'hour' => ':count saat',
+ 'a_hour' => '{1}bir saat|]1,Inf[:count saat',
+ 'h' => ':countsa',
+ 'minute' => ':count dakika',
+ 'a_minute' => '{1}bir dakika|]1,Inf[:count dakika',
+ 'min' => ':countdk',
+ 'second' => ':count saniye',
+ 'a_second' => '{1}birkaç saniye|]1,Inf[:count saniye',
+ 's' => ':countsn',
+ 'ago' => ':time önce',
+ 'from_now' => ':time sonra',
+ 'after' => ':time sonra',
+ 'before' => ':time önce',
+ 'diff_now' => 'şimdi',
+ 'diff_today' => 'bugün',
+ 'diff_today_regexp' => 'bugün(?:\\s+saat)?',
+ 'diff_yesterday' => 'dün',
+ 'diff_tomorrow' => 'yarın',
+ 'diff_tomorrow_regexp' => 'yarın(?:\\s+saat)?',
+ 'diff_before_yesterday' => 'evvelsi gün',
+ 'diff_after_tomorrow' => 'öbür gün',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[bugün saat] LT',
+ 'nextDay' => '[yarın saat] LT',
+ 'nextWeek' => '[gelecek] dddd [saat] LT',
+ 'lastDay' => '[dün] LT',
+ 'lastWeek' => '[geçen] dddd [saat] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ case 'd':
+ case 'D':
+ case 'Do':
+ case 'DD':
+ return $number;
+ default:
+ if ($number === 0) { // special case for zero
+ return "$number'ıncı";
+ }
+
+ static $suffixes = [
+ 1 => '\'inci',
+ 5 => '\'inci',
+ 8 => '\'inci',
+ 70 => '\'inci',
+ 80 => '\'inci',
+ 2 => '\'nci',
+ 7 => '\'nci',
+ 20 => '\'nci',
+ 50 => '\'nci',
+ 3 => '\'üncü',
+ 4 => '\'üncü',
+ 100 => '\'üncü',
+ 6 => '\'ncı',
+ 9 => '\'uncu',
+ 10 => '\'uncu',
+ 30 => '\'uncu',
+ 60 => '\'ıncı',
+ 90 => '\'ıncı',
+ ];
+
+ $lastDigit = $number % 10;
+
+ return $number.($suffixes[$lastDigit] ?? $suffixes[$number % 100 - $lastDigit] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
+ }
+ },
+ 'meridiem' => ['ÖÖ', 'ÖS', 'öö', 'ös'],
+ 'months' => ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
+ 'months_short' => ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara'],
+ 'weekdays' => ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'],
+ 'weekdays_short' => ['Paz', 'Pts', 'Sal', 'Çar', 'Per', 'Cum', 'Cts'],
+ 'weekdays_min' => ['Pz', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' ve '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tr_CY.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tr_CY.php
new file mode 100644
index 0000000..1937fec
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tr_CY.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/tr.php', [
+ 'weekdays_short' => ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'],
+ 'weekdays_min' => ['Pa', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'],
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'D.MM.YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'D MMMM YYYY dddd h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tr_TR.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tr_TR.php
new file mode 100644
index 0000000..dc8e935
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tr_TR.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/tr.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ts.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ts.php
new file mode 100644
index 0000000..525736b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ts.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ts_ZA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ts_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ts_ZA.php
new file mode 100644
index 0000000..37a24ec
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ts_ZA.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Sunguti', 'Nyenyenyani', 'Nyenyankulu', 'Dzivamisoko', 'Mudyaxihi', 'Khotavuxika', 'Mawuwani', 'Mhawuri', 'Ndzhati', 'Nhlangula', 'Hukuri', 'N\'wendzamhala'],
+ 'months_short' => ['Sun', 'Yan', 'Kul', 'Dzi', 'Mud', 'Kho', 'Maw', 'Mha', 'Ndz', 'Nhl', 'Huk', 'N\'w'],
+ 'weekdays' => ['Sonto', 'Musumbhunuku', 'Ravumbirhi', 'Ravunharhu', 'Ravumune', 'Ravuntlhanu', 'Mugqivela'],
+ 'weekdays_short' => ['Son', 'Mus', 'Bir', 'Har', 'Ne', 'Tlh', 'Mug'],
+ 'weekdays_min' => ['Son', 'Mus', 'Bir', 'Har', 'Ne', 'Tlh', 'Mug'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => 'malembe ya :count',
+ 'y' => 'malembe ya :count',
+ 'a_year' => 'malembe ya :count',
+
+ 'month' => 'tin’hweti ta :count',
+ 'm' => 'tin’hweti ta :count',
+ 'a_month' => 'tin’hweti ta :count',
+
+ 'week' => 'mavhiki ya :count',
+ 'w' => 'mavhiki ya :count',
+ 'a_week' => 'mavhiki ya :count',
+
+ 'day' => 'masiku :count',
+ 'd' => 'masiku :count',
+ 'a_day' => 'masiku :count',
+
+ 'hour' => 'tiawara ta :count',
+ 'h' => 'tiawara ta :count',
+ 'a_hour' => 'tiawara ta :count',
+
+ 'minute' => 'timinete ta :count',
+ 'min' => 'timinete ta :count',
+ 'a_minute' => 'timinete ta :count',
+
+ 'second' => 'tisekoni ta :count',
+ 's' => 'tisekoni ta :count',
+ 'a_second' => 'tisekoni ta :count',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tt.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tt.php
new file mode 100644
index 0000000..d67d896
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tt.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/tt_RU.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tt_RU.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tt_RU.php
new file mode 100644
index 0000000..38e42d0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tt_RU.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Rinat Norkin Pablo Saratxaga, Rinat Norkin pablo@mandrakesoft.com, rinat@taif.ru
+ */
+return [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'DD MMM, HH:mm',
+ 'LLLL' => 'DD MMMM YYYY, HH:mm',
+ ],
+ 'months' => ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'],
+ 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
+ 'weekdays' => ['якшәмбе', 'дышәмбе', 'сишәмбе', 'чәршәәмбе', 'пәнҗешмбе', 'җомга', 'шимбә'],
+ 'weekdays_short' => ['якш', 'дыш', 'сиш', 'чәрш', 'пәнҗ', 'җом', 'шим'],
+ 'weekdays_min' => ['якш', 'дыш', 'сиш', 'чәрш', 'пәнҗ', 'җом', 'шим'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'year' => ':count ел',
+ 'month' => ':count ай',
+ 'week' => ':count атна',
+ 'day' => ':count көн',
+ 'hour' => ':count сәгать',
+ 'minute' => ':count минут',
+ 'second' => ':count секунд',
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tt_RU@iqtelif.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tt_RU@iqtelif.php
new file mode 100644
index 0000000..16b8efb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tt_RU@iqtelif.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Reshat Sabiq tatar.iqtelif.i18n@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD.MM.YYYY',
+ ],
+ 'months' => ['Ğınwar', 'Fiwral\'', 'Mart', 'April', 'May', 'Yün', 'Yül', 'Awgust', 'Sintebír', 'Üktebír', 'Noyebír', 'Dikebír'],
+ 'months_short' => ['Ğın', 'Fiw', 'Mar', 'Apr', 'May', 'Yün', 'Yül', 'Awg', 'Sin', 'Ükt', 'Noy', 'Dik'],
+ 'weekdays' => ['Yekşembí', 'Düşembí', 'Sişembí', 'Çerşembí', 'Pencíşembí', 'Comğa', 'Şimbe'],
+ 'weekdays_short' => ['Yek', 'Düş', 'Siş', 'Çer', 'Pen', 'Com', 'Şim'],
+ 'weekdays_min' => ['Yek', 'Düş', 'Siş', 'Çer', 'Pen', 'Com', 'Şim'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ÖA', 'ÖS'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/twq.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/twq.php
new file mode 100644
index 0000000..e8ff278
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/twq.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/ses.php', [
+ 'meridiem' => ['Subbaahi', 'Zaarikay b'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tzl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tzl.php
new file mode 100644
index 0000000..50bf26d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tzl.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return [
+ 'year' => '[0,1]:count ar|:count ars',
+ 'y' => '[0,1]:count ar|:count ars',
+ 'month' => '[0,1]:count mes|:count mesen',
+ 'm' => '[0,1]:count mes|:count mesen',
+ 'week' => '[0,1]:count seifetziua|:count seifetziuas',
+ 'w' => '[0,1]:count seifetziua|:count seifetziuas',
+ 'day' => '[0,1]:count ziua|:count ziuas',
+ 'd' => '[0,1]:count ziua|:count ziuas',
+ 'hour' => '[0,1]:count þora|:count þoras',
+ 'h' => '[0,1]:count þora|:count þoras',
+ 'minute' => '[0,1]:count míut|:count míuts',
+ 'min' => '[0,1]:count míut|:count míuts',
+ 'second' => ':count secunds',
+ 's' => ':count secunds',
+
+ 'ago' => 'ja :time',
+ 'from_now' => 'osprei :time',
+
+ 'diff_yesterday' => 'ieiri',
+ 'diff_yesterday_regexp' => 'ieiri(?:\\s+à)?',
+ 'diff_today' => 'oxhi',
+ 'diff_today_regexp' => 'oxhi(?:\\s+à)?',
+ 'diff_tomorrow' => 'demà',
+ 'diff_tomorrow_regexp' => 'demà(?:\\s+à)?',
+
+ 'formats' => [
+ 'LT' => 'HH.mm',
+ 'LTS' => 'HH.mm.ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D. MMMM [dallas] YYYY',
+ 'LLL' => 'D. MMMM [dallas] YYYY HH.mm',
+ 'LLLL' => 'dddd, [li] D. MMMM [dallas] YYYY HH.mm',
+ ],
+
+ 'calendar' => [
+ 'sameDay' => '[oxhi à] LT',
+ 'nextDay' => '[demà à] LT',
+ 'nextWeek' => 'dddd [à] LT',
+ 'lastDay' => '[ieiri à] LT',
+ 'lastWeek' => '[sür el] dddd [lasteu à] LT',
+ 'sameElse' => 'L',
+ ],
+
+ 'meridiem' => ["D'A", "D'O"],
+ 'months' => ['Januar', 'Fevraglh', 'Març', 'Avrïu', 'Mai', 'Gün', 'Julia', 'Guscht', 'Setemvar', 'Listopäts', 'Noemvar', 'Zecemvar'],
+ 'months_short' => ['Jan', 'Fev', 'Mar', 'Avr', 'Mai', 'Gün', 'Jul', 'Gus', 'Set', 'Lis', 'Noe', 'Zec'],
+ 'weekdays' => ['Súladi', 'Lúneçi', 'Maitzi', 'Márcuri', 'Xhúadi', 'Viénerçi', 'Sáturi'],
+ 'weekdays_short' => ['Súl', 'Lún', 'Mai', 'Már', 'Xhú', 'Vié', 'Sát'],
+ 'weekdays_min' => ['Sú', 'Lú', 'Ma', 'Má', 'Xh', 'Vi', 'Sá'],
+ 'ordinal' => ':number.',
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tzm.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tzm.php
new file mode 100644
index 0000000..2a1a0f2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tzm.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - JD Isaacks
+ */
+return [
+ 'year' => '{1}ⴰⵙⴳⴰⵙ|:count ⵉⵙⴳⴰⵙⵏ',
+ 'month' => '{1}ⴰⵢoⵓⵔ|:count ⵉⵢⵢⵉⵔⵏ',
+ 'week' => ':count ⵉⵎⴰⵍⴰⵙⵙ',
+ 'day' => '{1}ⴰⵙⵙ|:count oⵙⵙⴰⵏ',
+ 'hour' => '{1}ⵙⴰⵄⴰ|:count ⵜⴰⵙⵙⴰⵄⵉⵏ',
+ 'minute' => '{1}ⵎⵉⵏⵓⴺ|:count ⵎⵉⵏⵓⴺ',
+ 'second' => '{1}ⵉⵎⵉⴽ|:count ⵉⵎⵉⴽ',
+ 'ago' => 'ⵢⴰⵏ :time',
+ 'from_now' => 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ :time',
+ 'diff_today' => 'ⴰⵙⴷⵅ',
+ 'diff_yesterday' => 'ⴰⵚⴰⵏⵜ',
+ 'diff_yesterday_regexp' => 'ⴰⵚⴰⵏⵜ(?:\\s+ⴴ)?',
+ 'diff_tomorrow' => 'ⴰⵙⴽⴰ',
+ 'diff_tomorrow_regexp' => 'ⴰⵙⴽⴰ(?:\\s+ⴴ)?',
+ 'diff_today_regexp' => 'ⴰⵙⴷⵅ(?:\\s+ⴴ)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[ⴰⵙⴷⵅ ⴴ] LT',
+ 'nextDay' => '[ⴰⵙⴽⴰ ⴴ] LT',
+ 'nextWeek' => 'dddd [ⴴ] LT',
+ 'lastDay' => '[ⴰⵚⴰⵏⵜ ⴴ] LT',
+ 'lastWeek' => 'dddd [ⴴ] LT',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⵏⴱⵉⵔ'],
+ 'months_short' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⵏⴱⵉⵔ'],
+ 'weekdays' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
+ 'weekdays_short' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
+ 'weekdays_min' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+ 'weekend' => [5, 6],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tzm_Latn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tzm_Latn.php
new file mode 100644
index 0000000..5840d20
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/tzm_Latn.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - JD Isaacks
+ */
+return [
+ 'year' => '{1}:count asgas|:count isgasn',
+ 'a_year' => 'asgas|:count isgasn',
+ 'month' => '{1}:count ayowr|:count iyyirn',
+ 'a_month' => 'ayowr|:count iyyirn',
+ 'week' => ':count imalass',
+ 'a_week' => ':imalass',
+ 'day' => '{1}:count ass|:count ossan',
+ 'a_day' => 'ass|:count ossan',
+ 'hour' => '{1}:count saɛa|:count tassaɛin',
+ 'a_hour' => '{1}saɛa|:count tassaɛin',
+ 'minute' => ':count minuḍ',
+ 'a_minute' => '{1}minuḍ|:count minuḍ',
+ 'second' => ':count imik',
+ 'a_second' => '{1}imik|:count imik',
+ 'ago' => 'yan :time',
+ 'from_now' => 'dadkh s yan :time',
+ 'diff_yesterday' => 'assant',
+ 'diff_yesterday_regexp' => 'assant(?:\\s+g)?',
+ 'diff_today' => 'asdkh',
+ 'diff_today_regexp' => 'asdkh(?:\\s+g)?',
+ 'diff_tomorrow' => 'aska',
+ 'diff_tomorrow_regexp' => 'aska(?:\\s+g)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[asdkh g] LT',
+ 'nextDay' => '[aska g] LT',
+ 'nextWeek' => 'dddd [g] LT',
+ 'lastDay' => '[assant g] LT',
+ 'lastWeek' => 'dddd [g] LT',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['innayr', 'brˤayrˤ', 'marˤsˤ', 'ibrir', 'mayyw', 'ywnyw', 'ywlywz', 'ɣwšt', 'šwtanbir', 'ktˤwbrˤ', 'nwwanbir', 'dwjnbir'],
+ 'months_short' => ['innayr', 'brˤayrˤ', 'marˤsˤ', 'ibrir', 'mayyw', 'ywnyw', 'ywlywz', 'ɣwšt', 'šwtanbir', 'ktˤwbrˤ', 'nwwanbir', 'dwjnbir'],
+ 'weekdays' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'],
+ 'weekdays_short' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'],
+ 'weekdays_min' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'],
+ 'meridiem' => ['Zdat azal', 'Ḍeffir aza'],
+ 'first_day_of_week' => 6,
+ 'day_of_first_week_of_year' => 1,
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ug.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ug.php
new file mode 100644
index 0000000..259b99a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ug.php
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Philippe Vaucher
+ * - Tsutomu Kuroda
+ * - yasinn
+ */
+return [
+ 'year' => '{1}'.'بىر يىل'.'|:count '.'يىل',
+ 'month' => '{1}'.'بىر ئاي'.'|:count '.'ئاي',
+ 'week' => '{1}'.'بىر ھەپتە'.'|:count '.'ھەپتە',
+ 'day' => '{1}'.'بىر كۈن'.'|:count '.'كۈن',
+ 'hour' => '{1}'.'بىر سائەت'.'|:count '.'سائەت',
+ 'minute' => '{1}'.'بىر مىنۇت'.'|:count '.'مىنۇت',
+ 'second' => '{1}'.'نەچچە سېكونت'.'|:count '.'سېكونت',
+ 'ago' => ':time بۇرۇن',
+ 'from_now' => ':time كېيىن',
+ 'diff_today' => 'بۈگۈن',
+ 'diff_yesterday' => 'تۆنۈگۈن',
+ 'diff_tomorrow' => 'ئەتە',
+ 'diff_tomorrow_regexp' => 'ئەتە(?:\\s+سائەت)?',
+ 'diff_today_regexp' => 'بۈگۈن(?:\\s+سائەت)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-DD',
+ 'LL' => 'YYYY-يىلىM-ئاينىڭD-كۈنى',
+ 'LLL' => 'YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm',
+ 'LLLL' => 'dddd، YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[بۈگۈن سائەت] LT',
+ 'nextDay' => '[ئەتە سائەت] LT',
+ 'nextWeek' => '[كېلەركى] dddd [سائەت] LT',
+ 'lastDay' => '[تۆنۈگۈن] LT',
+ 'lastWeek' => '[ئالدىنقى] dddd [سائەت] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return $number.'-كۈنى';
+ case 'w':
+ case 'W':
+ return $number.'-ھەپتە';
+ default:
+ return $number;
+ }
+ },
+ 'meridiem' => function ($hour, $minute) {
+ $time = $hour * 100 + $minute;
+ if ($time < 600) {
+ return 'يېرىم كېچە';
+ }
+ if ($time < 900) {
+ return 'سەھەر';
+ }
+ if ($time < 1130) {
+ return 'چۈشتىن بۇرۇن';
+ }
+ if ($time < 1230) {
+ return 'چۈش';
+ }
+ if ($time < 1800) {
+ return 'چۈشتىن كېيىن';
+ }
+
+ return 'كەچ';
+ },
+ 'months' => ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'],
+ 'months_short' => ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'],
+ 'weekdays' => ['يەكشەنبە', 'دۈشەنبە', 'سەيشەنبە', 'چارشەنبە', 'پەيشەنبە', 'جۈمە', 'شەنبە'],
+ 'weekdays_short' => ['يە', 'دۈ', 'سە', 'چا', 'پە', 'جۈ', 'شە'],
+ 'weekdays_min' => ['يە', 'دۈ', 'سە', 'چا', 'پە', 'جۈ', 'شە'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' ۋە '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ug_CN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ug_CN.php
new file mode 100644
index 0000000..deb828c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ug_CN.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Kunal Marwaha
+ * - Alim Boyaq
+ */
+return require __DIR__.'/ug.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uk.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uk.php
new file mode 100644
index 0000000..ab2d867
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uk.php
@@ -0,0 +1,208 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+$processHoursFunction = function (\Carbon\CarbonInterface $date, string $format) {
+ return $format.'о'.($date->hour === 11 ? 'б' : '').'] LT';
+};
+
+/*
+ * Authors:
+ * - Kunal Marwaha
+ * - Josh Soref
+ * - François B
+ * - Tim Fish
+ * - Serhan Apaydın
+ * - Max Mykhailenko
+ * - JD Isaacks
+ * - Max Kovpak
+ * - AucT
+ * - Philippe Vaucher
+ * - Ilya Shaplyko
+ * - Vadym Ievsieiev
+ * - Denys Kurets
+ * - Igor Kasyanchuk
+ * - Tsutomu Kuroda
+ * - tjku
+ * - Max Melentiev
+ * - Oleh
+ * - epaminond
+ * - Juanito Fatas
+ * - Vitalii Khustochka
+ * - Akira Matsuda
+ * - Christopher Dell
+ * - Enrique Vidal
+ * - Simone Carletti
+ * - Aaron Patterson
+ * - Andriy Tyurnikov
+ * - Nicolás Hock Isaza
+ * - Iwakura Taro
+ * - Andrii Ponomarov
+ * - alecrabbit
+ * - vystepanenko
+ * - AlexWalkerson
+ * - Andre Havryliuk (Andrend)
+ * - Max Datsenko (datsenko-md)
+ */
+return [
+ 'year' => ':count рік|:count роки|:count років',
+ 'y' => ':countр',
+ 'a_year' => '{1}рік|:count рік|:count роки|:count років',
+ 'month' => ':count місяць|:count місяці|:count місяців',
+ 'm' => ':countм',
+ 'a_month' => '{1}місяць|:count місяць|:count місяці|:count місяців',
+ 'week' => ':count тиждень|:count тижні|:count тижнів',
+ 'w' => ':countт',
+ 'a_week' => '{1}тиждень|:count тиждень|:count тижні|:count тижнів',
+ 'day' => ':count день|:count дні|:count днів',
+ 'd' => ':countд',
+ 'a_day' => '{1}день|:count день|:count дні|:count днів',
+ 'hour' => ':count година|:count години|:count годин',
+ 'h' => ':countг',
+ 'a_hour' => '{1}година|:count година|:count години|:count годин',
+ 'minute' => ':count хвилина|:count хвилини|:count хвилин',
+ 'min' => ':countхв',
+ 'a_minute' => '{1}хвилина|:count хвилина|:count хвилини|:count хвилин',
+ 'second' => ':count секунда|:count секунди|:count секунд',
+ 's' => ':countсек',
+ 'a_second' => '{1}декілька секунд|:count секунда|:count секунди|:count секунд',
+
+ 'hour_ago' => ':count годину|:count години|:count годин',
+ 'a_hour_ago' => '{1}годину|:count годину|:count години|:count годин',
+ 'minute_ago' => ':count хвилину|:count хвилини|:count хвилин',
+ 'a_minute_ago' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин',
+ 'second_ago' => ':count секунду|:count секунди|:count секунд',
+ 'a_second_ago' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд',
+
+ 'hour_from_now' => ':count годину|:count години|:count годин',
+ 'a_hour_from_now' => '{1}годину|:count годину|:count години|:count годин',
+ 'minute_from_now' => ':count хвилину|:count хвилини|:count хвилин',
+ 'a_minute_from_now' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин',
+ 'second_from_now' => ':count секунду|:count секунди|:count секунд',
+ 'a_second_from_now' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд',
+
+ 'hour_after' => ':count годину|:count години|:count годин',
+ 'a_hour_after' => '{1}годину|:count годину|:count години|:count годин',
+ 'minute_after' => ':count хвилину|:count хвилини|:count хвилин',
+ 'a_minute_after' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин',
+ 'second_after' => ':count секунду|:count секунди|:count секунд',
+ 'a_second_after' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд',
+
+ 'hour_before' => ':count годину|:count години|:count годин',
+ 'a_hour_before' => '{1}годину|:count годину|:count години|:count годин',
+ 'minute_before' => ':count хвилину|:count хвилини|:count хвилин',
+ 'a_minute_before' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин',
+ 'second_before' => ':count секунду|:count секунди|:count секунд',
+ 'a_second_before' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд',
+
+ 'ago' => ':time тому',
+ 'from_now' => 'за :time',
+ 'after' => ':time після',
+ 'before' => ':time до',
+ 'diff_now' => 'щойно',
+ 'diff_today' => 'Сьогодні',
+ 'diff_today_regexp' => 'Сьогодні(?:\\s+о)?',
+ 'diff_yesterday' => 'вчора',
+ 'diff_yesterday_regexp' => 'Вчора(?:\\s+о)?',
+ 'diff_tomorrow' => 'завтра',
+ 'diff_tomorrow_regexp' => 'Завтра(?:\\s+о)?',
+ 'diff_before_yesterday' => 'позавчора',
+ 'diff_after_tomorrow' => 'післязавтра',
+ 'period_recurrences' => 'один раз|:count рази|:count разів',
+ 'period_interval' => 'кожні :interval',
+ 'period_start_date' => 'з :date',
+ 'period_end_date' => 'до :date',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY, HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => function (\Carbon\CarbonInterface $date) use ($processHoursFunction) {
+ return $processHoursFunction($date, '[Сьогодні ');
+ },
+ 'nextDay' => function (\Carbon\CarbonInterface $date) use ($processHoursFunction) {
+ return $processHoursFunction($date, '[Завтра ');
+ },
+ 'nextWeek' => function (\Carbon\CarbonInterface $date) use ($processHoursFunction) {
+ return $processHoursFunction($date, '[У] dddd [');
+ },
+ 'lastDay' => function (\Carbon\CarbonInterface $date) use ($processHoursFunction) {
+ return $processHoursFunction($date, '[Вчора ');
+ },
+ 'lastWeek' => function (\Carbon\CarbonInterface $date) use ($processHoursFunction) {
+ switch ($date->dayOfWeek) {
+ case 0:
+ case 3:
+ case 5:
+ case 6:
+ return $processHoursFunction($date, '[Минулої] dddd [');
+ default:
+ return $processHoursFunction($date, '[Минулого] dddd [');
+ }
+ },
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ case 'M':
+ case 'd':
+ case 'DDD':
+ case 'w':
+ case 'W':
+ return $number.'-й';
+ case 'D':
+ return $number.'-го';
+ default:
+ return $number;
+ }
+ },
+ 'meridiem' => function ($hour) {
+ if ($hour < 4) {
+ return 'ночі';
+ }
+ if ($hour < 12) {
+ return 'ранку';
+ }
+ if ($hour < 17) {
+ return 'дня';
+ }
+
+ return 'вечора';
+ },
+ 'months' => ['січня', 'лютого', 'березня', 'квітня', 'травня', 'червня', 'липня', 'серпня', 'вересня', 'жовтня', 'листопада', 'грудня'],
+ 'months_standalone' => ['січень', 'лютий', 'березень', 'квітень', 'травень', 'червень', 'липень', 'серпень', 'вересень', 'жовтень', 'листопад', 'грудень'],
+ 'months_short' => ['січ', 'лют', 'бер', 'кві', 'тра', 'чер', 'лип', 'сер', 'вер', 'жов', 'лис', 'гру'],
+ 'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
+ 'weekdays' => function (\Carbon\CarbonInterface $date, $format, $index) {
+ static $words = [
+ 'nominative' => ['неділя', 'понеділок', 'вівторок', 'середа', 'четвер', 'п’ятниця', 'субота'],
+ 'accusative' => ['неділю', 'понеділок', 'вівторок', 'середу', 'четвер', 'п’ятницю', 'суботу'],
+ 'genitive' => ['неділі', 'понеділка', 'вівторка', 'середи', 'четверга', 'п’ятниці', 'суботи'],
+ ];
+
+ $nounCase = preg_match('/(\[(В|в|У|у)\])\s+dddd/', $format)
+ ? 'accusative'
+ : (
+ preg_match('/\[?(?:минулої|наступної)?\s*\]\s+dddd/', $format)
+ ? 'genitive'
+ : 'nominative'
+ );
+
+ return $words[$nounCase][$index] ?? null;
+ },
+ 'weekdays_short' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
+ 'weekdays_min' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' i '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uk_UA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uk_UA.php
new file mode 100644
index 0000000..5fc4317
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uk_UA.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/uk.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/unm.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/unm.php
new file mode 100644
index 0000000..d3f19f0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/unm.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/unm_US.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/unm_US.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/unm_US.php
new file mode 100644
index 0000000..fa5c374
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/unm_US.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['enikwsi', 'chkwali', 'xamokhwite', 'kwetayoxe', 'tainipen', 'kichinipen', 'lainipen', 'winaminke', 'kichitahkok', 'puksit', 'wini', 'muxkotae'],
+ 'months_short' => ['eni', 'chk', 'xam', 'kwe', 'tai', 'nip', 'lai', 'win', 'tah', 'puk', 'kun', 'mux'],
+ 'weekdays' => ['kentuwei', 'manteke', 'tusteke', 'lelai', 'tasteke', 'pelaiteke', 'sateteke'],
+ 'weekdays_short' => ['ken', 'man', 'tus', 'lel', 'tas', 'pel', 'sat'],
+ 'weekdays_min' => ['ken', 'man', 'tus', 'lel', 'tas', 'pel', 'sat'],
+ 'day_of_first_week_of_year' => 1,
+
+ // Too unreliable
+ /*
+ 'year' => ':count kaxtëne',
+ 'y' => ':count kaxtëne',
+ 'a_year' => ':count kaxtëne',
+
+ 'month' => ':count piskewëni kishux', // less reliable
+ 'm' => ':count piskewëni kishux', // less reliable
+ 'a_month' => ':count piskewëni kishux', // less reliable
+
+ 'week' => ':count kishku', // less reliable
+ 'w' => ':count kishku', // less reliable
+ 'a_week' => ':count kishku', // less reliable
+
+ 'day' => ':count kishku',
+ 'd' => ':count kishku',
+ 'a_day' => ':count kishku',
+
+ 'hour' => ':count xkuk', // less reliable
+ 'h' => ':count xkuk', // less reliable
+ 'a_hour' => ':count xkuk', // less reliable
+
+ 'minute' => ':count txituwàk', // less reliable
+ 'min' => ':count txituwàk', // less reliable
+ 'a_minute' => ':count txituwàk', // less reliable
+
+ 'second' => ':count nisha', // less reliable
+ 's' => ':count nisha', // less reliable
+ 'a_second' => ':count nisha', // less reliable
+ */
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ur.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ur.php
new file mode 100644
index 0000000..e55aff2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ur.php
@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+$months = [
+ 'جنوری',
+ 'فروری',
+ 'مارچ',
+ 'اپریل',
+ 'مئی',
+ 'جون',
+ 'جولائی',
+ 'اگست',
+ 'ستمبر',
+ 'اکتوبر',
+ 'نومبر',
+ 'دسمبر',
+];
+
+$weekdays = [
+ 'اتوار',
+ 'پیر',
+ 'منگل',
+ 'بدھ',
+ 'جمعرات',
+ 'جمعہ',
+ 'ہفتہ',
+];
+
+/*
+ * Authors:
+ * - Sawood Alam
+ * - Mehshan
+ * - Philippe Vaucher
+ * - Tsutomu Kuroda
+ * - tjku
+ * - Zaid Akram
+ * - Max Melentiev
+ * - hafezdivandari
+ * - Hossein Jabbari
+ * - nimamo
+ */
+return [
+ 'year' => 'ایک سال|:count سال',
+ 'month' => 'ایک ماہ|:count ماہ',
+ 'week' => ':count ہفتے',
+ 'day' => 'ایک دن|:count دن',
+ 'hour' => 'ایک گھنٹہ|:count گھنٹے',
+ 'minute' => 'ایک منٹ|:count منٹ',
+ 'second' => 'چند سیکنڈ|:count سیکنڈ',
+ 'ago' => ':time قبل',
+ 'from_now' => ':time بعد',
+ 'after' => ':time بعد',
+ 'before' => ':time پہلے',
+ 'diff_now' => 'اب',
+ 'diff_today' => 'آج',
+ 'diff_today_regexp' => 'آج(?:\\s+بوقت)?',
+ 'diff_yesterday' => 'گزشتہ کل',
+ 'diff_yesterday_regexp' => 'گذشتہ(?:\\s+روز)?(?:\\s+بوقت)?',
+ 'diff_tomorrow' => 'آئندہ کل',
+ 'diff_tomorrow_regexp' => 'کل(?:\\s+بوقت)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd، D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[آج بوقت] LT',
+ 'nextDay' => '[کل بوقت] LT',
+ 'nextWeek' => 'dddd [بوقت] LT',
+ 'lastDay' => '[گذشتہ روز بوقت] LT',
+ 'lastWeek' => '[گذشتہ] dddd [بوقت] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['صبح', 'شام'],
+ 'months' => $months,
+ 'months_short' => $months,
+ 'weekdays' => $weekdays,
+ 'weekdays_short' => $weekdays,
+ 'weekdays_min' => $weekdays,
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => ['، ', ' اور '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ur_IN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ur_IN.php
new file mode 100644
index 0000000..f81c84d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ur_IN.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Red Hat, Pune bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ur.php', [
+ 'formats' => [
+ 'L' => 'D/M/YY',
+ ],
+ 'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'weekdays' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'],
+ 'weekdays_short' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'],
+ 'weekdays_min' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ur_PK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ur_PK.php
new file mode 100644
index 0000000..8cd593d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ur_PK.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/ur.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'weekdays' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
+ 'weekdays_short' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
+ 'weekdays_min' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ص', 'ش'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz.php
new file mode 100644
index 0000000..61f3b64
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Dmitriy Shabanov
+ * - JD Isaacks
+ * - Inoyatulloh
+ * - Jamshid
+ * - aarkhipov
+ * - Philippe Vaucher
+ * - felixthemagnificent
+ * - Tsutomu Kuroda
+ * - tjku
+ * - Max Melentiev
+ * - Juanito Fatas
+ * - Alisher Ulugbekov
+ * - Ergashev Adizbek
+ */
+return [
+ 'year' => ':count йил',
+ 'a_year' => '{1}бир йил|:count йил',
+ 'y' => ':count й',
+ 'month' => ':count ой',
+ 'a_month' => '{1}бир ой|:count ой',
+ 'm' => ':count о',
+ 'week' => ':count ҳафта',
+ 'a_week' => '{1}бир ҳафта|:count ҳафта',
+ 'w' => ':count ҳ',
+ 'day' => ':count кун',
+ 'a_day' => '{1}бир кун|:count кун',
+ 'd' => ':count к',
+ 'hour' => ':count соат',
+ 'a_hour' => '{1}бир соат|:count соат',
+ 'h' => ':count с',
+ 'minute' => ':count дақиқа',
+ 'a_minute' => '{1}бир дақиқа|:count дақиқа',
+ 'min' => ':count д',
+ 'second' => ':count сония',
+ 'a_second' => '{1}сония|:count сония',
+ 's' => ':count с',
+ 'ago' => ':time аввал',
+ 'from_now' => 'Якин :time ичида',
+ 'after' => ':timeдан кейин',
+ 'before' => ':time олдин',
+ 'diff_now' => 'ҳозир',
+ 'diff_today' => 'Бугун',
+ 'diff_today_regexp' => 'Бугун(?:\\s+соат)?',
+ 'diff_yesterday' => 'Кеча',
+ 'diff_yesterday_regexp' => 'Кеча(?:\\s+соат)?',
+ 'diff_tomorrow' => 'Эртага',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'D MMMM YYYY, dddd HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Бугун соат] LT [да]',
+ 'nextDay' => '[Эртага] LT [да]',
+ 'nextWeek' => 'dddd [куни соат] LT [да]',
+ 'lastDay' => '[Кеча соат] LT [да]',
+ 'lastWeek' => '[Утган] dddd [куни соат] LT [да]',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['январ', 'феврал', 'март', 'апрел', 'май', 'июн', 'июл', 'август', 'сентябр', 'октябр', 'ноябр', 'декабр'],
+ 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
+ 'weekdays' => ['якшанба', 'душанба', 'сешанба', 'чоршанба', 'пайшанба', 'жума', 'шанба'],
+ 'weekdays_short' => ['якш', 'душ', 'сеш', 'чор', 'пай', 'жум', 'шан'],
+ 'weekdays_min' => ['як', 'ду', 'се', 'чо', 'па', 'жу', 'ша'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['эрталаб', 'кечаси'],
+ 'list' => [', ', ' ва '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_Arab.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_Arab.php
new file mode 100644
index 0000000..6871911
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_Arab.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/fa.php', [
+ 'weekdays' => ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
+ 'weekdays_short' => ['ی.', 'د.', 'س.', 'چ.', 'پ.', 'ج.', 'ش.'],
+ 'weekdays_min' => ['ی.', 'د.', 'س.', 'چ.', 'پ.', 'ج.', 'ش.'],
+ 'months' => ['جنوری', 'فبروری', 'مارچ', 'اپریل', 'می', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
+ 'months_short' => ['جنو', 'فبر', 'مار', 'اپر', 'می', 'جون', 'جول', 'اگس', 'سپت', 'اکت', 'نوم', 'دسم'],
+ 'first_day_of_week' => 6,
+ 'weekend' => [4, 5],
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-dd',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'YYYY MMMM D HH:mm',
+ 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_Cyrl.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_Cyrl.php
new file mode 100644
index 0000000..e875469
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_Cyrl.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/uz.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/yy',
+ 'LL' => 'D MMM, YYYY',
+ 'LLL' => 'D MMMM, YYYY HH:mm',
+ 'LLLL' => 'dddd, DD MMMM, YYYY HH:mm',
+ ],
+ 'meridiem' => ['ТО', 'ТК'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_Latn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_Latn.php
new file mode 100644
index 0000000..ecceeaa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_Latn.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Josh Soref
+ * - Rasulbek
+ * - Ilyosjon Kamoldinov (ilyosjon09)
+ */
+return [
+ 'year' => ':count yil',
+ 'a_year' => '{1}bir yil|:count yil',
+ 'y' => ':count y',
+ 'month' => ':count oy',
+ 'a_month' => '{1}bir oy|:count oy',
+ 'm' => ':count o',
+ 'week' => ':count hafta',
+ 'a_week' => '{1}bir hafta|:count hafta',
+ 'w' => ':count h',
+ 'day' => ':count kun',
+ 'a_day' => '{1}bir kun|:count kun',
+ 'd' => ':count k',
+ 'hour' => ':count soat',
+ 'a_hour' => '{1}bir soat|:count soat',
+ 'h' => ':count soat',
+ 'minute' => ':count daqiqa',
+ 'a_minute' => '{1}bir daqiqa|:count daqiqa',
+ 'min' => ':count d',
+ 'second' => ':count soniya',
+ 'a_second' => '{1}soniya|:count soniya',
+ 's' => ':count son.',
+ 'ago' => ':time avval',
+ 'from_now' => 'Yaqin :time ichida',
+ 'after' => ':timedan keyin',
+ 'before' => ':time oldin',
+ 'diff_yesterday' => 'Kecha',
+ 'diff_yesterday_regexp' => 'Kecha(?:\\s+soat)?',
+ 'diff_today' => 'Bugun',
+ 'diff_today_regexp' => 'Bugun(?:\\s+soat)?',
+ 'diff_tomorrow' => 'Ertaga',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'D MMMM YYYY, dddd HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Bugun soat] LT [da]',
+ 'nextDay' => '[Ertaga] LT [da]',
+ 'nextWeek' => 'dddd [kuni soat] LT [da]',
+ 'lastDay' => '[Kecha soat] LT [da]',
+ 'lastWeek' => '[O\'tgan] dddd [kuni soat] LT [da]',
+ 'sameElse' => 'L',
+ ],
+ 'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul', 'Avgust', 'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'],
+ 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'Iyun', 'Iyul', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'],
+ 'weekdays' => ['Yakshanba', 'Dushanba', 'Seshanba', 'Chorshanba', 'Payshanba', 'Juma', 'Shanba'],
+ 'weekdays_short' => ['Yak', 'Dush', 'Sesh', 'Chor', 'Pay', 'Jum', 'Shan'],
+ 'weekdays_min' => ['Ya', 'Du', 'Se', 'Cho', 'Pa', 'Ju', 'Sha'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' va '],
+ 'meridiem' => ['TO', 'TK'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_UZ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_UZ.php
new file mode 100644
index 0000000..d41bfee
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_UZ.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Bobir Ismailov Bobir Ismailov, Pablo Saratxaga, Mashrab Kuvatov bobir_is@yahoo.com, pablo@mandrakesoft.com, kmashrab@uni-bremen.de
+ */
+return array_replace_recursive(require __DIR__.'/uz_Latn.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul', 'Avgust', 'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'],
+ 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'Iyn', 'Iyl', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'],
+ 'weekdays' => ['Yakshanba', 'Dushanba', 'Seshanba', 'Chorshanba', 'Payshanba', 'Juma', 'Shanba'],
+ 'weekdays_short' => ['Yak', 'Du', 'Se', 'Cho', 'Pay', 'Ju', 'Sha'],
+ 'weekdays_min' => ['Yak', 'Du', 'Se', 'Cho', 'Pay', 'Ju', 'Sha'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_UZ@cyrillic.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_UZ@cyrillic.php
new file mode 100644
index 0000000..2fa967c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/uz_UZ@cyrillic.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Mashrab Kuvatov Mashrab Kuvatov, Pablo Saratxaga kmashrab@uni-bremen.de, pablo@mandrakesoft.com
+ */
+return array_replace_recursive(require __DIR__.'/uz.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['Январ', 'Феврал', 'Март', 'Апрел', 'Май', 'Июн', 'Июл', 'Август', 'Сентябр', 'Октябр', 'Ноябр', 'Декабр'],
+ 'months_short' => ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
+ 'weekdays' => ['Якшанба', 'Душанба', 'Сешанба', 'Чоршанба', 'Пайшанба', 'Жума', 'Шанба'],
+ 'weekdays_short' => ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай', 'Жум', 'Шан'],
+ 'weekdays_min' => ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай', 'Жум', 'Шан'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vai.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vai.php
new file mode 100644
index 0000000..3e6fce2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vai.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'weekdays' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
+ 'weekdays_short' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
+ 'weekdays_min' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
+ 'months' => ['ꖨꖕ ꕪꕴ ꔞꔀꕮꕊ', 'ꕒꕡꖝꖕ', 'ꕾꖺ', 'ꖢꖕ', 'ꖑꕱ', 'ꖱꘋ', 'ꖱꕞꔤ', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋꕔꕿ ꕸꖃꗏ', 'ꖨꖕ ꕪꕴ ꗏꖺꕮꕊ'],
+ 'months_short' => ['ꖨꖕꔞ', 'ꕒꕡ', 'ꕾꖺ', 'ꖢꖕ', 'ꖑꕱ', 'ꖱꘋ', 'ꖱꕞ', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋ', 'ꖨꖕꗏ'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd, D MMMM YYYY h:mm a',
+ ],
+
+ 'year' => ':count ꕀ', // less reliable
+ 'y' => ':count ꕀ', // less reliable
+ 'a_year' => ':count ꕀ', // less reliable
+
+ 'second' => ':count ꗱꕞꕯꕊ', // less reliable
+ 's' => ':count ꗱꕞꕯꕊ', // less reliable
+ 'a_second' => ':count ꗱꕞꕯꕊ', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vai_Latn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vai_Latn.php
new file mode 100644
index 0000000..b76c4bc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vai_Latn.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'weekdays' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'],
+ 'weekdays_short' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'],
+ 'weekdays_min' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'],
+ 'months' => ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6', '7', 'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'],
+ 'months_short' => ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6', '7', 'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'h:mm a',
+ 'LTS' => 'h:mm:ss a',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm a',
+ 'LLLL' => 'dddd, D MMMM YYYY h:mm a',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vai_Vaii.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vai_Vaii.php
new file mode 100644
index 0000000..7b029a8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vai_Vaii.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/vai.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ve.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ve.php
new file mode 100644
index 0000000..7f10aeb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ve.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/ve_ZA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ve_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ve_ZA.php
new file mode 100644
index 0000000..5eb2b91
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ve_ZA.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Phando', 'Luhuhi', 'Ṱhafamuhwe', 'Lambamai', 'Shundunthule', 'Fulwi', 'Fulwana', 'Ṱhangule', 'Khubvumedzi', 'Tshimedzi', 'Ḽara', 'Nyendavhusiku'],
+ 'months_short' => ['Pha', 'Luh', 'Fam', 'Lam', 'Shu', 'Lwi', 'Lwa', 'Ngu', 'Khu', 'Tsh', 'Ḽar', 'Nye'],
+ 'weekdays' => ['Swondaha', 'Musumbuluwo', 'Ḽavhuvhili', 'Ḽavhuraru', 'Ḽavhuṋa', 'Ḽavhuṱanu', 'Mugivhela'],
+ 'weekdays_short' => ['Swo', 'Mus', 'Vhi', 'Rar', 'ṋa', 'Ṱan', 'Mug'],
+ 'weekdays_min' => ['Swo', 'Mus', 'Vhi', 'Rar', 'ṋa', 'Ṱan', 'Mug'],
+ 'day_of_first_week_of_year' => 1,
+
+ // Too unreliable
+ /*
+ 'day' => ':count vhege', // less reliable
+ 'd' => ':count vhege', // less reliable
+ 'a_day' => ':count vhege', // less reliable
+
+ 'hour' => ':count watshi', // less reliable
+ 'h' => ':count watshi', // less reliable
+ 'a_hour' => ':count watshi', // less reliable
+
+ 'minute' => ':count watshi', // less reliable
+ 'min' => ':count watshi', // less reliable
+ 'a_minute' => ':count watshi', // less reliable
+
+ 'second' => ':count Mu', // less reliable
+ 's' => ':count Mu', // less reliable
+ 'a_second' => ':count Mu', // less reliable
+
+ 'week' => ':count vhege',
+ 'w' => ':count vhege',
+ 'a_week' => ':count vhege',
+ */
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vi.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vi.php
new file mode 100644
index 0000000..73e2852
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vi.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Andre Polykanine A.K.A. Menelion Elensúlë
+ * - JD Isaacks
+ */
+return [
+ 'year' => ':count năm',
+ 'a_year' => '{1}một năm|]1, Inf[:count năm',
+ 'y' => ':count năm',
+ 'month' => ':count tháng',
+ 'a_month' => '{1}một tháng|]1, Inf[:count tháng',
+ 'm' => ':count tháng',
+ 'week' => ':count tuần',
+ 'a_week' => '{1}một tuần|]1, Inf[:count tuần',
+ 'w' => ':count tuần',
+ 'day' => ':count ngày',
+ 'a_day' => '{1}một ngày|]1, Inf[:count ngày',
+ 'd' => ':count ngày',
+ 'hour' => ':count giờ',
+ 'a_hour' => '{1}một giờ|]1, Inf[:count giờ',
+ 'h' => ':count giờ',
+ 'minute' => ':count phút',
+ 'a_minute' => '{1}một phút|]1, Inf[:count phút',
+ 'min' => ':count phút',
+ 'second' => ':count giây',
+ 'a_second' => '{1}vài giây|]1, Inf[:count giây',
+ 's' => ':count giây',
+ 'ago' => ':time trước',
+ 'from_now' => ':time tới',
+ 'after' => ':time sau',
+ 'before' => ':time trước',
+ 'diff_now' => 'bây giờ',
+ 'diff_today' => 'Hôm',
+ 'diff_today_regexp' => 'Hôm(?:\\s+nay)?(?:\\s+lúc)?',
+ 'diff_yesterday' => 'Hôm qua',
+ 'diff_yesterday_regexp' => 'Hôm(?:\\s+qua)?(?:\\s+lúc)?',
+ 'diff_tomorrow' => 'Ngày mai',
+ 'diff_tomorrow_regexp' => 'Ngày(?:\\s+mai)?(?:\\s+lúc)?',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM [năm] YYYY',
+ 'LLL' => 'D MMMM [năm] YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM [năm] YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Hôm nay lúc] LT',
+ 'nextDay' => '[Ngày mai lúc] LT',
+ 'nextWeek' => 'dddd [tuần tới lúc] LT',
+ 'lastDay' => '[Hôm qua lúc] LT',
+ 'lastWeek' => 'dddd [tuần trước lúc] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['SA', 'CH'],
+ 'months' => ['tháng 1', 'tháng 2', 'tháng 3', 'tháng 4', 'tháng 5', 'tháng 6', 'tháng 7', 'tháng 8', 'tháng 9', 'tháng 10', 'tháng 11', 'tháng 12'],
+ 'months_short' => ['Th01', 'Th02', 'Th03', 'Th04', 'Th05', 'Th06', 'Th07', 'Th08', 'Th09', 'Th10', 'Th11', 'Th12'],
+ 'weekdays' => ['chủ nhật', 'thứ hai', 'thứ ba', 'thứ tư', 'thứ năm', 'thứ sáu', 'thứ bảy'],
+ 'weekdays_short' => ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
+ 'weekdays_min' => ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => [', ', ' và '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vi_VN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vi_VN.php
new file mode 100644
index 0000000..77b2dce
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vi_VN.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/vi.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vo.php
new file mode 100644
index 0000000..a956a78
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vo.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
+ 'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY-MM-dd',
+ 'LL' => 'YYYY MMM D',
+ 'LLL' => 'YYYY MMMM D HH:mm',
+ 'LLLL' => 'YYYY MMMM D, dddd HH:mm',
+ ],
+
+ 'year' => ':count yel',
+ 'y' => ':count yel',
+ 'a_year' => ':count yel',
+
+ 'month' => ':count mul',
+ 'm' => ':count mul',
+ 'a_month' => ':count mul',
+
+ 'week' => ':count vig',
+ 'w' => ':count vig',
+ 'a_week' => ':count vig',
+
+ 'day' => ':count del',
+ 'd' => ':count del',
+ 'a_day' => ':count del',
+
+ 'hour' => ':count düp',
+ 'h' => ':count düp',
+ 'a_hour' => ':count düp',
+
+ 'minute' => ':count minut',
+ 'min' => ':count minut',
+ 'a_minute' => ':count minut',
+
+ 'second' => ':count sekun',
+ 's' => ':count sekun',
+ 'a_second' => ':count sekun',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vun.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vun.php
new file mode 100644
index 0000000..f8cc72c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/vun.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['utuko', 'kyiukonyi'],
+ 'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
+ 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
+ 'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wa.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wa.php
new file mode 100644
index 0000000..f6dc4cc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wa.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/wa_BE.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wa_BE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wa_BE.php
new file mode 100644
index 0000000..a76d80d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wa_BE.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Djan SACRE Pablo Saratxaga pablo@mandrakesoft.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['di djanvî', 'di fevrî', 'di måss', 'd’ avri', 'di may', 'di djun', 'di djulete', 'd’ awousse', 'di setimbe', 'd’ octôbe', 'di nôvimbe', 'di decimbe'],
+ 'months_short' => ['dja', 'fev', 'mås', 'avr', 'may', 'djn', 'djl', 'awo', 'set', 'oct', 'nôv', 'dec'],
+ 'weekdays' => ['dimegne', 'londi', 'mårdi', 'mierkidi', 'djudi', 'vénrdi', 'semdi'],
+ 'weekdays_short' => ['dim', 'lon', 'mår', 'mie', 'dju', 'vén', 'sem'],
+ 'weekdays_min' => ['dim', 'lon', 'mår', 'mie', 'dju', 'vén', 'sem'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'year' => ':count anêye',
+ 'y' => ':count anêye',
+ 'a_year' => ':count anêye',
+
+ 'month' => ':count meûs',
+ 'm' => ':count meûs',
+ 'a_month' => ':count meûs',
+
+ 'week' => ':count samwinne',
+ 'w' => ':count samwinne',
+ 'a_week' => ':count samwinne',
+
+ 'day' => ':count djoû',
+ 'd' => ':count djoû',
+ 'a_day' => ':count djoû',
+
+ 'hour' => ':count eure',
+ 'h' => ':count eure',
+ 'a_hour' => ':count eure',
+
+ 'minute' => ':count munute',
+ 'min' => ':count munute',
+ 'a_minute' => ':count munute',
+
+ 'second' => ':count Sigonde',
+ 's' => ':count Sigonde',
+ 'a_second' => ':count Sigonde',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wae.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wae.php
new file mode 100644
index 0000000..bf57f23
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wae.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/wae_CH.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wae_CH.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wae_CH.php
new file mode 100644
index 0000000..2af50b4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wae_CH.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Walser Translation Team ml@translate-wae.ch
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'YYYY-MM-DD',
+ ],
+ 'months' => ['Jenner', 'Hornig', 'Märze', 'Abrille', 'Meije', 'Bráčet', 'Heiwet', 'Öigšte', 'Herbštmánet', 'Wímánet', 'Wintermánet', 'Chrištmánet'],
+ 'months_short' => ['Jen', 'Hor', 'Mär', 'Abr', 'Mei', 'Brá', 'Hei', 'Öig', 'Her', 'Wím', 'Win', 'Chr'],
+ 'weekdays' => ['Suntag', 'Mäntag', 'Zischtag', 'Mittwuch', 'Frontag', 'Fritag', 'Samschtag'],
+ 'weekdays_short' => ['Sun', 'Män', 'Zis', 'Mit', 'Fro', 'Fri', 'Sam'],
+ 'weekdays_min' => ['Sun', 'Män', 'Zis', 'Mit', 'Fro', 'Fri', 'Sam'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+
+ 'month' => ':count Maano', // less reliable
+ 'm' => ':count Maano', // less reliable
+ 'a_month' => ':count Maano', // less reliable
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wal.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wal.php
new file mode 100644
index 0000000..e8ec40f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wal.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/wal_ET.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wal_ET.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wal_ET.php
new file mode 100644
index 0000000..a4e619a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wal_ET.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Ge'ez Frontier Foundation locales@geez.org
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'],
+ 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
+ 'weekdays' => ['ወጋ', 'ሳይኖ', 'ማቆሳኛ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ'],
+ 'weekdays_short' => ['ወጋ ', 'ሳይኖ', 'ማቆሳ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ '],
+ 'weekdays_min' => ['ወጋ ', 'ሳይኖ', 'ማቆሳ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ '],
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['ማለዶ', 'ቃማ'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wo.php
new file mode 100644
index 0000000..74b95df
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wo.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/wo_SN.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wo_SN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wo_SN.php
new file mode 100644
index 0000000..f8a85b3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/wo_SN.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - The Debian Project Christian Perrier bubulle@debian.org
+ */
+return [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD.MM.YYYY',
+ 'LL' => 'MMMM DD, YYYY',
+ 'LLL' => 'DD MMM HH:mm',
+ 'LLLL' => 'MMMM DD, YYYY HH:mm',
+ ],
+ 'months' => ['sanwiy\'e', 'feebriy\'e', 'mars', 'awril', 'me', 'suwen', 'sulet', 'uut', 'septaambar', 'oktoobar', 'nowaambar', 'desaambar'],
+ 'months_short' => ['san', 'fee', 'mar', 'awr', 'me ', 'suw', 'sul', 'uut', 'sep', 'okt', 'now', 'des'],
+ 'weekdays' => ['dib\'eer', 'altine', 'talaata', 'allarba', 'alxames', 'ajjuma', 'gaawu'],
+ 'weekdays_short' => ['dib', 'alt', 'tal', 'all', 'alx', 'ajj', 'gaa'],
+ 'weekdays_min' => ['dib', 'alt', 'tal', 'all', 'alx', 'ajj', 'gaa'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'year' => ':count at',
+ 'month' => ':count wèr',
+ 'week' => ':count ayubés',
+ 'day' => ':count bés',
+ 'hour' => ':count waxtu',
+ 'minute' => ':count simili',
+ 'second' => ':count saa',
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/xh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/xh.php
new file mode 100644
index 0000000..e88c78d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/xh.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/xh_ZA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/xh_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/xh_ZA.php
new file mode 100644
index 0000000..910f831
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/xh_ZA.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['eyoMqungu', 'eyoMdumba', 'eyoKwindla', 'uTshazimpuzi', 'uCanzibe', 'eyeSilimela', 'eyeKhala', 'eyeThupa', 'eyoMsintsi', 'eyeDwarha', 'eyeNkanga', 'eyoMnga'],
+ 'months_short' => ['Mqu', 'Mdu', 'Kwi', 'Tsh', 'Can', 'Sil', 'Kha', 'Thu', 'Msi', 'Dwa', 'Nka', 'Mng'],
+ 'weekdays' => ['iCawa', 'uMvulo', 'lwesiBini', 'lwesiThathu', 'ulweSine', 'lwesiHlanu', 'uMgqibelo'],
+ 'weekdays_short' => ['Caw', 'Mvu', 'Bin', 'Tha', 'Sin', 'Hla', 'Mgq'],
+ 'weekdays_min' => ['Caw', 'Mvu', 'Bin', 'Tha', 'Sin', 'Hla', 'Mgq'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count ihlobo', // less reliable
+ 'y' => ':count ihlobo', // less reliable
+ 'a_year' => ':count ihlobo', // less reliable
+
+ 'hour' => ':count iwotshi', // less reliable
+ 'h' => ':count iwotshi', // less reliable
+ 'a_hour' => ':count iwotshi', // less reliable
+
+ 'minute' => ':count ingqalelo', // less reliable
+ 'min' => ':count ingqalelo', // less reliable
+ 'a_minute' => ':count ingqalelo', // less reliable
+
+ 'second' => ':count nceda', // less reliable
+ 's' => ':count nceda', // less reliable
+ 'a_second' => ':count nceda', // less reliable
+
+ 'month' => ':count inyanga',
+ 'm' => ':count inyanga',
+ 'a_month' => ':count inyanga',
+
+ 'week' => ':count veki',
+ 'w' => ':count veki',
+ 'a_week' => ':count veki',
+
+ 'day' => ':count imini',
+ 'd' => ':count imini',
+ 'a_day' => ':count imini',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/xog.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/xog.php
new file mode 100644
index 0000000..063977c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/xog.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['Munkyo', 'Eigulo'],
+ 'weekdays' => ['Sabiiti', 'Balaza', 'Owokubili', 'Owokusatu', 'Olokuna', 'Olokutaanu', 'Olomukaaga'],
+ 'weekdays_short' => ['Sabi', 'Bala', 'Kubi', 'Kusa', 'Kuna', 'Kuta', 'Muka'],
+ 'weekdays_min' => ['Sabi', 'Bala', 'Kubi', 'Kusa', 'Kuna', 'Kuta', 'Muka'],
+ 'months' => ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi', 'Juuni', 'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba', 'Desemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul', 'Agu', 'Seb', 'Oki', 'Nov', 'Des'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yav.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yav.php
new file mode 100644
index 0000000..e44cde6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yav.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'meridiem' => ['kiɛmɛ́ɛm', 'kisɛ́ndɛ'],
+ 'weekdays' => ['sɔ́ndiɛ', 'móndie', 'muányáŋmóndie', 'metúkpíápɛ', 'kúpélimetúkpiapɛ', 'feléte', 'séselé'],
+ 'weekdays_short' => ['sd', 'md', 'mw', 'et', 'kl', 'fl', 'ss'],
+ 'weekdays_min' => ['sd', 'md', 'mw', 'et', 'kl', 'fl', 'ss'],
+ 'months' => ['pikítíkítie, oólí ú kutúan', 'siɛyɛ́, oóli ú kándíɛ', 'ɔnsúmbɔl, oóli ú kátátúɛ', 'mesiŋ, oóli ú kénie', 'ensil, oóli ú kátánuɛ', 'ɔsɔn', 'efute', 'pisuyú', 'imɛŋ i puɔs', 'imɛŋ i putúk,oóli ú kátíɛ', 'makandikɛ', 'pilɔndɔ́'],
+ 'months_short' => ['o.1', 'o.2', 'o.3', 'o.4', 'o.5', 'o.6', 'o.7', 'o.8', 'o.9', 'o.10', 'o.11', 'o.12'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'D/M/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yi.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yi.php
new file mode 100644
index 0000000..8f32022
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yi.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/yi_US.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yi_US.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yi_US.php
new file mode 100644
index 0000000..f764d36
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yi_US.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - http://www.uyip.org/ Pablo Saratxaga pablo@mandrakesoft.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['יאַנואַר', 'פֿעברואַר', 'מערץ', 'אַפּריל', 'מיי', 'יוני', 'יולי', 'אויגוסט', 'סעפּטעמבער', 'אקטאבער', 'נאוועמבער', 'דעצעמבער'],
+ 'months_short' => ['יאַנ', 'פֿעב', 'מאַר', 'אַפּר', 'מײַ ', 'יונ', 'יול', 'אױג', 'סעפּ', 'אָקט', 'נאָװ', 'דעצ'],
+ 'weekdays' => ['זונטיק', 'מאָנטיק', 'דינסטיק', 'מיטװאָך', 'דאָנערשטיק', 'פֿרײַטיק', 'שבת'],
+ 'weekdays_short' => ['זונ\'', 'מאָנ\'', 'דינ\'', 'מיט\'', 'דאָנ\'', 'פֿרײַ\'', 'שבת'],
+ 'weekdays_min' => ['זונ\'', 'מאָנ\'', 'דינ\'', 'מיט\'', 'דאָנ\'', 'פֿרײַ\'', 'שבת'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => ':count יאר',
+ 'y' => ':count יאר',
+ 'a_year' => ':count יאר',
+
+ 'month' => ':count חודש',
+ 'm' => ':count חודש',
+ 'a_month' => ':count חודש',
+
+ 'week' => ':count וואָך',
+ 'w' => ':count וואָך',
+ 'a_week' => ':count וואָך',
+
+ 'day' => ':count טאָג',
+ 'd' => ':count טאָג',
+ 'a_day' => ':count טאָג',
+
+ 'hour' => ':count שעה',
+ 'h' => ':count שעה',
+ 'a_hour' => ':count שעה',
+
+ 'minute' => ':count מינוט',
+ 'min' => ':count מינוט',
+ 'a_minute' => ':count מינוט',
+
+ 'second' => ':count סעקונדע',
+ 's' => ':count סעקונדע',
+ 'a_second' => ':count סעקונדע',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yo.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yo.php
new file mode 100644
index 0000000..0a82981
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yo.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - François B
+ * - Atolagbe Abisoye
+ */
+return [
+ 'year' => 'ọdún :count',
+ 'a_year' => '{1}ọdún kan|ọdún :count',
+ 'month' => 'osù :count',
+ 'a_month' => '{1}osù kan|osù :count',
+ 'week' => 'ọsẹ :count',
+ 'a_week' => '{1}ọsẹ kan|ọsẹ :count',
+ 'day' => 'ọjọ́ :count',
+ 'a_day' => '{1}ọjọ́ kan|ọjọ́ :count',
+ 'hour' => 'wákati :count',
+ 'a_hour' => '{1}wákati kan|wákati :count',
+ 'minute' => 'ìsẹjú :count',
+ 'a_minute' => '{1}ìsẹjú kan|ìsẹjú :count',
+ 'second' => 'iaayá :count',
+ 'a_second' => '{1}ìsẹjú aayá die|aayá :count',
+ 'ago' => ':time kọjá',
+ 'from_now' => 'ní :time',
+ 'diff_yesterday' => 'Àna',
+ 'diff_yesterday_regexp' => 'Àna(?:\\s+ni)?',
+ 'diff_today' => 'Ònì',
+ 'diff_today_regexp' => 'Ònì(?:\\s+ni)?',
+ 'diff_tomorrow' => 'Ọ̀la',
+ 'diff_tomorrow_regexp' => 'Ọ̀la(?:\\s+ni)?',
+ 'formats' => [
+ 'LT' => 'h:mm A',
+ 'LTS' => 'h:mm:ss A',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY h:mm A',
+ 'LLLL' => 'dddd, D MMMM YYYY h:mm A',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[Ònì ni] LT',
+ 'nextDay' => '[Ọ̀la ni] LT',
+ 'nextWeek' => 'dddd [Ọsẹ̀ tón\'bọ] [ni] LT',
+ 'lastDay' => '[Àna ni] LT',
+ 'lastWeek' => 'dddd [Ọsẹ̀ tólọ́] [ni] LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => 'ọjọ́ :number',
+ 'months' => ['Sẹ́rẹ́', 'Èrèlè', 'Ẹrẹ̀nà', 'Ìgbé', 'Èbibi', 'Òkùdu', 'Agẹmo', 'Ògún', 'Owewe', 'Ọ̀wàrà', 'Bélú', 'Ọ̀pẹ̀̀'],
+ 'months_short' => ['Sẹ́r', 'Èrl', 'Ẹrn', 'Ìgb', 'Èbi', 'Òkù', 'Agẹ', 'Ògú', 'Owe', 'Ọ̀wà', 'Bél', 'Ọ̀pẹ̀̀'],
+ 'weekdays' => ['Àìkú', 'Ajé', 'Ìsẹ́gun', 'Ọjọ́rú', 'Ọjọ́bọ', 'Ẹtì', 'Àbámẹ́ta'],
+ 'weekdays_short' => ['Àìk', 'Ajé', 'Ìsẹ́', 'Ọjr', 'Ọjb', 'Ẹtì', 'Àbá'],
+ 'weekdays_min' => ['Àì', 'Aj', 'Ìs', 'Ọr', 'Ọb', 'Ẹt', 'Àb'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'meridiem' => ['Àárọ̀', 'Ọ̀sán'],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yo_BJ.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yo_BJ.php
new file mode 100644
index 0000000..f06bb99
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yo_BJ.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array_replace_recursive(require __DIR__.'/yo.php', [
+ 'meridiem' => ['Àárɔ̀', 'Ɔ̀sán'],
+ 'weekdays' => ['Ɔjɔ́ Àìkú', 'Ɔjɔ́ Ajé', 'Ɔjɔ́ Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɔjɔ́ Ɛtì', 'Ɔjɔ́ Àbámɛ́ta'],
+ 'weekdays_short' => ['Àìkú', 'Ajé', 'Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɛtì', 'Àbámɛ́ta'],
+ 'weekdays_min' => ['Àìkú', 'Ajé', 'Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɛtì', 'Àbámɛ́ta'],
+ 'months' => ['Oshù Shɛ́rɛ́', 'Oshù Èrèlè', 'Oshù Ɛrɛ̀nà', 'Oshù Ìgbé', 'Oshù Ɛ̀bibi', 'Oshù Òkúdu', 'Oshù Agɛmɔ', 'Oshù Ògún', 'Oshù Owewe', 'Oshù Ɔ̀wàrà', 'Oshù Bélú', 'Oshù Ɔ̀pɛ̀'],
+ 'months_short' => ['Shɛ́rɛ́', 'Èrèlè', 'Ɛrɛ̀nà', 'Ìgbé', 'Ɛ̀bibi', 'Òkúdu', 'Agɛmɔ', 'Ògún', 'Owewe', 'Ɔ̀wàrà', 'Bélú', 'Ɔ̀pɛ̀'],
+ 'first_day_of_week' => 1,
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd, D MMMM YYYY HH:mm',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yo_NG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yo_NG.php
new file mode 100644
index 0000000..92934bc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yo_NG.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/yo.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue.php
new file mode 100644
index 0000000..ce233a4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/yue_HK.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue_HK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue_HK.php
new file mode 100644
index 0000000..4e7d5c3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue_HK.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/zh_HK.php', [
+ 'formats' => [
+ 'L' => 'YYYY年MM月DD日 dddd',
+ ],
+ 'months' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+ 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+ 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
+ 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'first_day_of_week' => 0,
+ 'day_of_first_week_of_year' => 1,
+ 'meridiem' => ['上午', '下午'],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue_Hans.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue_Hans.php
new file mode 100644
index 0000000..007d071
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue_Hans.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/zh_Hans.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue_Hant.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue_Hant.php
new file mode 100644
index 0000000..24797f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yue_Hant.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/zh_Hant.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yuw.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yuw.php
new file mode 100644
index 0000000..8efdc93
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yuw.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/yuw_PG.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yuw_PG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yuw_PG.php
new file mode 100644
index 0000000..b99ad2e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/yuw_PG.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Information from native speakers Hannah Sarvasy nungon.localization@gmail.com
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YY',
+ ],
+ 'months' => ['jenuari', 'febuari', 'mas', 'epril', 'mei', 'jun', 'julai', 'ögus', 'septemba', 'öktoba', 'nöwemba', 'diksemba'],
+ 'months_short' => ['jen', 'feb', 'mas', 'epr', 'mei', 'jun', 'jul', 'ögu', 'sep', 'ökt', 'nöw', 'dis'],
+ 'weekdays' => ['sönda', 'mönda', 'sinda', 'mitiwö', 'sogipbono', 'nenggo', 'söndanggie'],
+ 'weekdays_short' => ['sön', 'mön', 'sin', 'mit', 'soi', 'nen', 'sab'],
+ 'weekdays_min' => ['sön', 'mön', 'sin', 'mit', 'soi', 'nen', 'sab'],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zgh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zgh.php
new file mode 100644
index 0000000..4d2c3b3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zgh.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - BAKTETE Miloud
+ */
+return [
+ 'year' => ':count ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ',
+ 'a_year' => 'ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ',
+ 'y' => ':count ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ',
+ 'month' => ':count ⵡⴰⵢⵢⵓⵔ|:count ⴰⵢⵢⵓⵔⵏ',
+ 'a_month' => 'ⵉⴷⵊ ⵡⴰⵢⵢⵓⵔ|:count ⴰⵢⵢⵓⵔⵏ',
+ 'm' => ':count ⴰⵢⵢⵓⵔⵏ',
+ 'week' => ':count ⵉⵎⴰⵍⴰⵙⵙ|:count ⵉⵎⴰⵍⴰⵙⵙⵏ',
+ 'a_week' => 'ⵉⵛⵜ ⵉⵎⴰⵍⴰⵙⵙ|:count ⵉⵎⴰⵍⴰⵙⵙⵏ',
+ 'w' => ':count ⵉⵎⴰⵍⴰⵙⵙ.',
+ 'day' => ':count ⵡⴰⵙⵙ|:count ⵓⵙⵙⴰⵏ',
+ 'a_day' => 'ⵉⴷⵊ ⵡⴰⵙⵙ|:count ⵓⵙⵙⴰⵏ',
+ 'd' => ':count ⵓ',
+ 'hour' => ':count ⵜⵙⵔⴰⴳⵜ|:count ⵜⵉⵙⵔⴰⴳⵉⵏ',
+ 'a_hour' => 'ⵉⵛⵜ ⵜⵙⵔⴰⴳⵜ|:count ⵜⵉⵙⵔⴰⴳⵉⵏ',
+ 'h' => ':count ⵜ',
+ 'minute' => ':count ⵜⵓⵙⴷⵉⴷⵜ|:count ⵜⵓⵙⴷⵉⴷⵉⵏ',
+ 'a_minute' => 'ⵉⵛⵜ ⵜⵓⵙⴷⵉⴷⵜ|:count ⵜⵓⵙⴷⵉⴷⵉⵏ',
+ 'min' => ':count ⵜⵓⵙ',
+ 'second' => ':count ⵜⵙⵉⵏⵜ|:count ⵜⵉⵙⵉⵏⴰ',
+ 'a_second' => 'ⴽⵔⴰ ⵜⵉⵙⵉⵏⴰ|:count ⵜⵉⵙⵉⵏⴰ',
+ 's' => ':count ⵜ',
+ 'ago' => 'ⵣⴳ :time',
+ 'from_now' => 'ⴷⴳ :time',
+ 'after' => ':time ⴰⵡⴰⵔ',
+ 'before' => ':time ⴷⴰⵜ',
+ 'diff_now' => 'ⴰⴷⵡⴰⵍⵉ',
+ 'diff_today' => 'ⴰⵙⵙ',
+ 'diff_today_regexp' => 'ⴰⵙⵙ(?:\\s+ⴰ/ⴰⴷ)?(?:\\s+ⴳ)?',
+ 'diff_yesterday' => 'ⴰⵙⵙⵏⵏⴰⵟ',
+ 'diff_yesterday_regexp' => 'ⴰⵙⵙⵏⵏⴰⵟ(?:\\s+ⴳ)?',
+ 'diff_tomorrow' => 'ⴰⵙⴽⴽⴰ',
+ 'diff_tomorrow_regexp' => 'ⴰⵙⴽⴽⴰ(?:\\s+ⴳ)?',
+ 'diff_before_yesterday' => 'ⴼⵔ ⵉⴹⵏⵏⴰⵟ',
+ 'diff_after_tomorrow' => 'ⵏⴰⴼ ⵓⵙⴽⴽⴰ',
+ 'period_recurrences' => ':count ⵜⵉⴽⴽⴰⵍ',
+ 'period_interval' => 'ⴽⵓ :interval',
+ 'period_start_date' => 'ⴳ :date',
+ 'period_end_date' => 'ⵉ :date',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'DD/MM/YYYY',
+ 'LL' => 'D MMMM YYYY',
+ 'LLL' => 'D MMMM YYYY HH:mm',
+ 'LLLL' => 'dddd D MMMM YYYY HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[ⴰⵙⵙ ⴰ/ⴰⴷ ⴳ] LT',
+ 'nextDay' => '[ⴰⵙⴽⴽⴰ ⴳ] LT',
+ 'nextWeek' => 'dddd [ⴳ] LT',
+ 'lastDay' => '[ⴰⵙⵙⵏⵏⴰⵟ ⴳ] LT',
+ 'lastWeek' => 'dddd [ⴰⵎⴳⴳⴰⵔⵓ ⴳ] LT',
+ 'sameElse' => 'L',
+ ],
+ 'meridiem' => ['ⵜⵉⴼⴰⵡⵜ', 'ⵜⴰⴷⴳⴳⵯⴰⵜ'],
+ 'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'],
+ 'months_short' => ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ', 'ⵎⴰⵢ', 'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ', 'ⴽⵟⵓ', 'ⵏⵓⵡ', 'ⴷⵓⵊ'],
+ 'weekdays' => ['ⵓⵙⴰⵎⴰⵙ', 'ⵡⴰⵢⵏⴰⵙ', 'ⵓⵙⵉⵏⴰⵙ', 'ⵡⴰⴽⵕⴰⵙ', 'ⵓⴽⵡⴰⵙ', 'ⵓⵙⵉⵎⵡⴰⵙ', 'ⵓⵙⵉⴹⵢⴰⵙ'],
+ 'weekdays_short' => ['ⵓⵙⴰ', 'ⵡⴰⵢ', 'ⵓⵙⵉ', 'ⵡⴰⴽ', 'ⵓⴽⵡ', 'ⵓⵙⵉⵎ', 'ⵓⵙⵉⴹ'],
+ 'weekdays_min' => ['ⵓⵙⴰ', 'ⵡⴰⵢ', 'ⵓⵙⵉ', 'ⵡⴰⴽ', 'ⵓⴽⵡ', 'ⵓⵙⵉⵎ', 'ⵓⵙⵉⴹ'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 1,
+ 'list' => [', ', ' ⴷ '],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh.php
new file mode 100644
index 0000000..1187c3d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - xuri
+ * - sycuato
+ * - bokideckonja
+ * - Luo Ning
+ * - William Yang (williamyang233)
+ */
+return array_merge(require __DIR__.'/zh_Hans.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY/MM/DD',
+ 'LL' => 'YYYY年M月D日',
+ 'LLL' => 'YYYY年M月D日 A h点mm分',
+ 'LLLL' => 'YYYY年M月D日dddd A h点mm分',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_CN.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_CN.php
new file mode 100644
index 0000000..9c05d5a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_CN.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - monkeycon
+ * - François B
+ * - Jason Katz-Brown
+ * - Serhan Apaydın
+ * - Matt Johnson
+ * - JD Isaacks
+ * - Zeno Zeng
+ * - Chris Hemp
+ * - shankesgk2
+ */
+return array_merge(require __DIR__.'/zh.php', [
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY/MM/DD',
+ 'LL' => 'YYYY年M月D日',
+ 'LLL' => 'YYYY年M月D日Ah点mm分',
+ 'LLLL' => 'YYYY年M月D日ddddAh点mm分',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_HK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_HK.php
new file mode 100644
index 0000000..c3ee9fc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_HK.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return require __DIR__.'/zh_Hant_HK.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans.php
new file mode 100644
index 0000000..9b91785
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans.php
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - monkeycon
+ * - François B
+ * - Jason Katz-Brown
+ * - Konstantin Konev
+ * - Chris Lam
+ * - Serhan Apaydın
+ * - Gary Lo
+ * - JD Isaacks
+ * - Chris Hemp
+ * - shankesgk2
+ * - Daniel Cheung (danvim)
+ */
+return [
+ 'year' => ':count:optional-space年',
+ 'y' => ':count:optional-space年',
+ 'month' => ':count:optional-space个月',
+ 'm' => ':count:optional-space个月',
+ 'week' => ':count:optional-space周',
+ 'w' => ':count:optional-space周',
+ 'day' => ':count:optional-space天',
+ 'd' => ':count:optional-space天',
+ 'hour' => ':count:optional-space小时',
+ 'h' => ':count:optional-space小时',
+ 'minute' => ':count:optional-space分钟',
+ 'min' => ':count:optional-space分钟',
+ 'second' => ':count:optional-space秒',
+ 'a_second' => '{1}几秒|]1,Inf[:count:optional-space秒',
+ 's' => ':count:optional-space秒',
+ 'ago' => ':time前',
+ 'from_now' => ':time后',
+ 'after' => ':time后',
+ 'before' => ':time前',
+ 'diff_now' => '现在',
+ 'diff_today' => '今天',
+ 'diff_yesterday' => '昨天',
+ 'diff_tomorrow' => '明天',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY/MM/DD',
+ 'LL' => 'YYYY年M月D日',
+ 'LLL' => 'YYYY年M月D日 HH:mm',
+ 'LLLL' => 'YYYY年M月D日dddd HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[今天]LT',
+ 'nextDay' => '[明天]LT',
+ 'nextWeek' => '[下]ddddLT',
+ 'lastDay' => '[昨天]LT',
+ 'lastWeek' => '[上]ddddLT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return $number.'日';
+ case 'M':
+ return $number.'月';
+ case 'w':
+ case 'W':
+ return $number.'周';
+ default:
+ return $number;
+ }
+ },
+ 'meridiem' => function ($hour, $minute) {
+ $time = $hour * 100 + $minute;
+ if ($time < 600) {
+ return '凌晨';
+ }
+ if ($time < 900) {
+ return '早上';
+ }
+ if ($time < 1130) {
+ return '上午';
+ }
+ if ($time < 1230) {
+ return '中午';
+ }
+ if ($time < 1800) {
+ return '下午';
+ }
+
+ return '晚上';
+ },
+ 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+ 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
+ 'weekdays_short' => ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+ 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => '',
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_HK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_HK.php
new file mode 100644
index 0000000..007d071
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_HK.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/zh_Hans.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_MO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_MO.php
new file mode 100644
index 0000000..007d071
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_MO.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/zh_Hans.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_SG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_SG.php
new file mode 100644
index 0000000..007d071
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_SG.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/zh_Hans.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant.php
new file mode 100644
index 0000000..a27b610
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant.php
@@ -0,0 +1,111 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Adam
+ * - monkeycon
+ * - François B
+ * - Jason Katz-Brown
+ * - Chris Lam
+ * - Serhan Apaydın
+ * - Gary Lo
+ * - JD Isaacks
+ * - Chris Hemp
+ * - Eddie
+ * - KID
+ * - shankesgk2
+ * - Daniel Cheung (danvim)
+ */
+return [
+ 'year' => ':count:optional-space年',
+ 'y' => ':count:optional-space年',
+ 'month' => ':count:optional-space個月',
+ 'm' => ':count:optional-space月',
+ 'week' => ':count:optional-space週',
+ 'w' => ':count:optional-space週',
+ 'day' => ':count:optional-space天',
+ 'd' => ':count:optional-space天',
+ 'hour' => ':count:optional-space小時',
+ 'h' => ':count:optional-space小時',
+ 'minute' => ':count:optional-space分鐘',
+ 'min' => ':count:optional-space分鐘',
+ 'second' => ':count:optional-space秒',
+ 'a_second' => '{1}幾秒|]1,Inf[:count:optional-space秒',
+ 's' => ':count:optional-space秒',
+ 'ago' => ':time前',
+ 'from_now' => ':time後',
+ 'after' => ':time後',
+ 'before' => ':time前',
+ 'diff_now' => '現在',
+ 'diff_today' => '今天',
+ 'diff_yesterday' => '昨天',
+ 'diff_tomorrow' => '明天',
+ 'formats' => [
+ 'LT' => 'HH:mm',
+ 'LTS' => 'HH:mm:ss',
+ 'L' => 'YYYY/MM/DD',
+ 'LL' => 'YYYY年M月D日',
+ 'LLL' => 'YYYY年M月D日 HH:mm',
+ 'LLLL' => 'YYYY年M月D日dddd HH:mm',
+ ],
+ 'calendar' => [
+ 'sameDay' => '[今天] LT',
+ 'nextDay' => '[明天] LT',
+ 'nextWeek' => '[下]dddd LT',
+ 'lastDay' => '[昨天] LT',
+ 'lastWeek' => '[上]dddd LT',
+ 'sameElse' => 'L',
+ ],
+ 'ordinal' => function ($number, $period) {
+ switch ($period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return $number.'日';
+ case 'M':
+ return $number.'月';
+ case 'w':
+ case 'W':
+ return $number.'周';
+ default:
+ return $number;
+ }
+ },
+ 'meridiem' => function ($hour, $minute) {
+ $time = $hour * 100 + $minute;
+ if ($time < 600) {
+ return '凌晨';
+ }
+ if ($time < 900) {
+ return '早上';
+ }
+ if ($time < 1130) {
+ return '上午';
+ }
+ if ($time < 1230) {
+ return '中午';
+ }
+ if ($time < 1800) {
+ return '下午';
+ }
+
+ return '晚上';
+ },
+ 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+ 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
+ 'weekdays_short' => ['週日', '週一', '週二', '週三', '週四', '週五', '週六'],
+ 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'first_day_of_week' => 1,
+ 'day_of_first_week_of_year' => 4,
+ 'list' => '',
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_HK.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_HK.php
new file mode 100644
index 0000000..24797f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_HK.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/zh_Hant.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_MO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_MO.php
new file mode 100644
index 0000000..24797f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_MO.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/zh_Hant.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_TW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_TW.php
new file mode 100644
index 0000000..24797f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_TW.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return require __DIR__.'/zh_Hant.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_MO.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_MO.php
new file mode 100644
index 0000000..1c86d47
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_MO.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - tarunvelli
+ * - Eddie
+ * - KID
+ * - shankesgk2
+ */
+return array_replace_recursive(require __DIR__.'/zh_Hant.php', [
+ 'after' => ':time后',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_SG.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_SG.php
new file mode 100644
index 0000000..c451a56
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_SG.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/zh.php', [
+ 'formats' => [
+ 'L' => 'YYYY年MM月DD日',
+ ],
+ 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ 'months_short' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+ 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
+ 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
+ 'day_of_first_week_of_year' => 1,
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php
new file mode 100644
index 0000000..c6789ed
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return require __DIR__.'/zh_Hant_TW.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_YUE.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_YUE.php
new file mode 100644
index 0000000..b0d9ba8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zh_YUE.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org
+ */
+return array_replace_recursive(require __DIR__.'/zh.php', [
+ 'formats' => [
+ 'L' => 'YYYY-MM-DD',
+ ],
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zu.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zu.php
new file mode 100644
index 0000000..9a6cce0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zu.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Unknown default region, use the first alphabetically.
+ */
+return require __DIR__.'/zu_ZA.php';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zu_ZA.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zu_ZA.php
new file mode 100644
index 0000000..6bfb72f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/zu_ZA.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Authors:
+ * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
+ */
+return array_replace_recursive(require __DIR__.'/en.php', [
+ 'formats' => [
+ 'L' => 'DD/MM/YYYY',
+ ],
+ 'months' => ['Januwari', 'Februwari', 'Mashi', 'Ephreli', 'Meyi', 'Juni', 'Julayi', 'Agasti', 'Septhemba', 'Okthoba', 'Novemba', 'Disemba'],
+ 'months_short' => ['Jan', 'Feb', 'Mas', 'Eph', 'Mey', 'Jun', 'Jul', 'Aga', 'Sep', 'Okt', 'Nov', 'Dis'],
+ 'weekdays' => ['iSonto', 'uMsombuluko', 'uLwesibili', 'uLwesithathu', 'uLwesine', 'uLwesihlanu', 'uMgqibelo'],
+ 'weekdays_short' => ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'],
+ 'weekdays_min' => ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'],
+ 'day_of_first_week_of_year' => 1,
+
+ 'year' => 'kweminyaka engu-:count',
+ 'y' => 'kweminyaka engu-:count',
+ 'a_year' => 'kweminyaka engu-:count',
+
+ 'month' => 'izinyanga ezingu-:count',
+ 'm' => 'izinyanga ezingu-:count',
+ 'a_month' => 'izinyanga ezingu-:count',
+
+ 'week' => 'lwamasonto angu-:count',
+ 'w' => 'lwamasonto angu-:count',
+ 'a_week' => 'lwamasonto angu-:count',
+
+ 'day' => 'ezingaba ngu-:count',
+ 'd' => 'ezingaba ngu-:count',
+ 'a_day' => 'ezingaba ngu-:count',
+
+ 'hour' => 'amahora angu-:count',
+ 'h' => 'amahora angu-:count',
+ 'a_hour' => 'amahora angu-:count',
+
+ 'minute' => 'ngemizuzu engu-:count',
+ 'min' => 'ngemizuzu engu-:count',
+ 'a_minute' => 'ngemizuzu engu-:count',
+
+ 'second' => 'imizuzwana engu-:count',
+ 's' => 'imizuzwana engu-:count',
+ 'a_second' => 'imizuzwana engu-:count',
+]);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Language.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Language.php
new file mode 100644
index 0000000..3790285
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Language.php
@@ -0,0 +1,341 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use JsonSerializable;
+use ReturnTypeWillChange;
+
+class Language implements JsonSerializable
+{
+ /**
+ * @var array
+ */
+ protected static $languagesNames;
+
+ /**
+ * @var array
+ */
+ protected static $regionsNames;
+
+ /**
+ * @var string
+ */
+ protected $id;
+
+ /**
+ * @var string
+ */
+ protected $code;
+
+ /**
+ * @var string|null
+ */
+ protected $variant;
+
+ /**
+ * @var string|null
+ */
+ protected $region;
+
+ /**
+ * @var array
+ */
+ protected $names;
+
+ /**
+ * @var string
+ */
+ protected $isoName;
+
+ /**
+ * @var string
+ */
+ protected $nativeName;
+
+ public function __construct(string $id)
+ {
+ $this->id = str_replace('-', '_', $id);
+ $parts = explode('_', $this->id);
+ $this->code = $parts[0];
+
+ if (isset($parts[1])) {
+ if (!preg_match('/^[A-Z]+$/', $parts[1])) {
+ $this->variant = $parts[1];
+ $parts[1] = $parts[2] ?? null;
+ }
+ if ($parts[1]) {
+ $this->region = $parts[1];
+ }
+ }
+ }
+
+ /**
+ * Get the list of the known languages.
+ *
+ * @return array
+ */
+ public static function all()
+ {
+ if (!static::$languagesNames) {
+ static::$languagesNames = require __DIR__.'/List/languages.php';
+ }
+
+ return static::$languagesNames;
+ }
+
+ /**
+ * Get the list of the known regions.
+ *
+ * @return array
+ */
+ public static function regions()
+ {
+ if (!static::$regionsNames) {
+ static::$regionsNames = require __DIR__.'/List/regions.php';
+ }
+
+ return static::$regionsNames;
+ }
+
+ /**
+ * Get both isoName and nativeName as an array.
+ *
+ * @return array
+ */
+ public function getNames(): array
+ {
+ if (!$this->names) {
+ $this->names = static::all()[$this->code] ?? [
+ 'isoName' => $this->code,
+ 'nativeName' => $this->code,
+ ];
+ }
+
+ return $this->names;
+ }
+
+ /**
+ * Returns the original locale ID.
+ *
+ * @return string
+ */
+ public function getId(): string
+ {
+ return $this->id;
+ }
+
+ /**
+ * Returns the code of the locale "en"/"fr".
+ *
+ * @return string
+ */
+ public function getCode(): string
+ {
+ return $this->code;
+ }
+
+ /**
+ * Returns the variant code such as cyrl/latn.
+ *
+ * @return string|null
+ */
+ public function getVariant(): ?string
+ {
+ return $this->variant;
+ }
+
+ /**
+ * Returns the variant such as Cyrillic/Latin.
+ *
+ * @return string|null
+ */
+ public function getVariantName(): ?string
+ {
+ if ($this->variant === 'Latn') {
+ return 'Latin';
+ }
+
+ if ($this->variant === 'Cyrl') {
+ return 'Cyrillic';
+ }
+
+ return $this->variant;
+ }
+
+ /**
+ * Returns the region part of the locale.
+ *
+ * @return string|null
+ */
+ public function getRegion(): ?string
+ {
+ return $this->region;
+ }
+
+ /**
+ * Returns the region name for the current language.
+ *
+ * @return string|null
+ */
+ public function getRegionName(): ?string
+ {
+ return $this->region ? (static::regions()[$this->region] ?? $this->region) : null;
+ }
+
+ /**
+ * Returns the long ISO language name.
+ *
+ * @return string
+ */
+ public function getFullIsoName(): string
+ {
+ if (!$this->isoName) {
+ $this->isoName = $this->getNames()['isoName'];
+ }
+
+ return $this->isoName;
+ }
+
+ /**
+ * Set the ISO language name.
+ *
+ * @param string $isoName
+ */
+ public function setIsoName(string $isoName): self
+ {
+ $this->isoName = $isoName;
+
+ return $this;
+ }
+
+ /**
+ * Return the full name of the language in this language.
+ *
+ * @return string
+ */
+ public function getFullNativeName(): string
+ {
+ if (!$this->nativeName) {
+ $this->nativeName = $this->getNames()['nativeName'];
+ }
+
+ return $this->nativeName;
+ }
+
+ /**
+ * Set the name of the language in this language.
+ *
+ * @param string $nativeName
+ */
+ public function setNativeName(string $nativeName): self
+ {
+ $this->nativeName = $nativeName;
+
+ return $this;
+ }
+
+ /**
+ * Returns the short ISO language name.
+ *
+ * @return string
+ */
+ public function getIsoName(): string
+ {
+ $name = $this->getFullIsoName();
+
+ return trim(strstr($name, ',', true) ?: $name);
+ }
+
+ /**
+ * Get the short name of the language in this language.
+ *
+ * @return string
+ */
+ public function getNativeName(): string
+ {
+ $name = $this->getFullNativeName();
+
+ return trim(strstr($name, ',', true) ?: $name);
+ }
+
+ /**
+ * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable.
+ *
+ * @return string
+ */
+ public function getIsoDescription()
+ {
+ $region = $this->getRegionName();
+ $variant = $this->getVariantName();
+
+ return $this->getIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
+ }
+
+ /**
+ * Get a string with short native name, region in parentheses if applicable, variant in parentheses if applicable.
+ *
+ * @return string
+ */
+ public function getNativeDescription()
+ {
+ $region = $this->getRegionName();
+ $variant = $this->getVariantName();
+
+ return $this->getNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
+ }
+
+ /**
+ * Get a string with long ISO name, region in parentheses if applicable, variant in parentheses if applicable.
+ *
+ * @return string
+ */
+ public function getFullIsoDescription()
+ {
+ $region = $this->getRegionName();
+ $variant = $this->getVariantName();
+
+ return $this->getFullIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
+ }
+
+ /**
+ * Get a string with long native name, region in parentheses if applicable, variant in parentheses if applicable.
+ *
+ * @return string
+ */
+ public function getFullNativeDescription()
+ {
+ $region = $this->getRegionName();
+ $variant = $this->getVariantName();
+
+ return $this->getFullNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
+ }
+
+ /**
+ * Returns the original locale ID.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->getId();
+ }
+
+ /**
+ * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable.
+ *
+ * @return string
+ */
+ #[ReturnTypeWillChange]
+ public function jsonSerialize()
+ {
+ return $this->getIsoDescription();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php
new file mode 100644
index 0000000..d71c888
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace Carbon\Laravel;
+
+use Carbon\Carbon;
+use Carbon\CarbonImmutable;
+use Carbon\CarbonInterval;
+use Carbon\CarbonPeriod;
+use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
+use Illuminate\Events\Dispatcher;
+use Illuminate\Events\EventDispatcher;
+use Illuminate\Support\Carbon as IlluminateCarbon;
+use Illuminate\Support\Facades\Date;
+use Throwable;
+
+class ServiceProvider extends \Illuminate\Support\ServiceProvider
+{
+ public function boot()
+ {
+ $this->updateLocale();
+
+ if (!$this->app->bound('events')) {
+ return;
+ }
+
+ $service = $this;
+ $events = $this->app['events'];
+
+ if ($this->isEventDispatcher($events)) {
+ $events->listen(class_exists('Illuminate\Foundation\Events\LocaleUpdated') ? 'Illuminate\Foundation\Events\LocaleUpdated' : 'locale.changed', function () use ($service) {
+ $service->updateLocale();
+ });
+ }
+ }
+
+ public function updateLocale()
+ {
+ $app = $this->app && method_exists($this->app, 'getLocale') ? $this->app : app('translator');
+ $locale = $app->getLocale();
+ Carbon::setLocale($locale);
+ CarbonImmutable::setLocale($locale);
+ CarbonPeriod::setLocale($locale);
+ CarbonInterval::setLocale($locale);
+
+ if (class_exists(IlluminateCarbon::class)) {
+ IlluminateCarbon::setLocale($locale);
+ }
+
+ if (class_exists(Date::class)) {
+ try {
+ $root = Date::getFacadeRoot();
+ $root->setLocale($locale);
+ } catch (Throwable $e) {
+ // Non Carbon class in use in Date facade
+ }
+ }
+ }
+
+ public function register()
+ {
+ // Needed for Laravel < 5.3 compatibility
+ }
+
+ protected function isEventDispatcher($instance)
+ {
+ return $instance instanceof EventDispatcher
+ || $instance instanceof Dispatcher
+ || $instance instanceof DispatcherContract;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/List/languages.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/List/languages.php
new file mode 100644
index 0000000..5b5d9a1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/List/languages.php
@@ -0,0 +1,1239 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return [
+ /*
+ * ISO 639-2
+ */
+ 'ab' => [
+ 'isoName' => 'Abkhazian',
+ 'nativeName' => 'аҧсуа бызшәа, аҧсшәа',
+ ],
+ 'aa' => [
+ 'isoName' => 'Afar',
+ 'nativeName' => 'Afaraf',
+ ],
+ 'af' => [
+ 'isoName' => 'Afrikaans',
+ 'nativeName' => 'Afrikaans',
+ ],
+ 'ak' => [
+ 'isoName' => 'Akan',
+ 'nativeName' => 'Akan',
+ ],
+ 'sq' => [
+ 'isoName' => 'Albanian',
+ 'nativeName' => 'Shqip',
+ ],
+ 'am' => [
+ 'isoName' => 'Amharic',
+ 'nativeName' => 'አማርኛ',
+ ],
+ 'ar' => [
+ 'isoName' => 'Arabic',
+ 'nativeName' => 'العربية',
+ ],
+ 'an' => [
+ 'isoName' => 'Aragonese',
+ 'nativeName' => 'aragonés',
+ ],
+ 'hy' => [
+ 'isoName' => 'Armenian',
+ 'nativeName' => 'Հայերեն',
+ ],
+ 'as' => [
+ 'isoName' => 'Assamese',
+ 'nativeName' => 'অসমীয়া',
+ ],
+ 'av' => [
+ 'isoName' => 'Avaric',
+ 'nativeName' => 'авар мацӀ, магӀарул мацӀ',
+ ],
+ 'ae' => [
+ 'isoName' => 'Avestan',
+ 'nativeName' => 'avesta',
+ ],
+ 'ay' => [
+ 'isoName' => 'Aymara',
+ 'nativeName' => 'aymar aru',
+ ],
+ 'az' => [
+ 'isoName' => 'Azerbaijani',
+ 'nativeName' => 'azərbaycan dili',
+ ],
+ 'bm' => [
+ 'isoName' => 'Bambara',
+ 'nativeName' => 'bamanankan',
+ ],
+ 'ba' => [
+ 'isoName' => 'Bashkir',
+ 'nativeName' => 'башҡорт теле',
+ ],
+ 'eu' => [
+ 'isoName' => 'Basque',
+ 'nativeName' => 'euskara, euskera',
+ ],
+ 'be' => [
+ 'isoName' => 'Belarusian',
+ 'nativeName' => 'беларуская мова',
+ ],
+ 'bn' => [
+ 'isoName' => 'Bengali',
+ 'nativeName' => 'বাংলা',
+ ],
+ 'bh' => [
+ 'isoName' => 'Bihari languages',
+ 'nativeName' => 'भोजपुरी',
+ ],
+ 'bi' => [
+ 'isoName' => 'Bislama',
+ 'nativeName' => 'Bislama',
+ ],
+ 'bs' => [
+ 'isoName' => 'Bosnian',
+ 'nativeName' => 'bosanski jezik',
+ ],
+ 'br' => [
+ 'isoName' => 'Breton',
+ 'nativeName' => 'brezhoneg',
+ ],
+ 'bg' => [
+ 'isoName' => 'Bulgarian',
+ 'nativeName' => 'български език',
+ ],
+ 'my' => [
+ 'isoName' => 'Burmese',
+ 'nativeName' => 'ဗမာစာ',
+ ],
+ 'ca' => [
+ 'isoName' => 'Catalan, Valencian',
+ 'nativeName' => 'català, valencià',
+ ],
+ 'ch' => [
+ 'isoName' => 'Chamorro',
+ 'nativeName' => 'Chamoru',
+ ],
+ 'ce' => [
+ 'isoName' => 'Chechen',
+ 'nativeName' => 'нохчийн мотт',
+ ],
+ 'ny' => [
+ 'isoName' => 'Chichewa, Chewa, Nyanja',
+ 'nativeName' => 'chiCheŵa, chinyanja',
+ ],
+ 'zh' => [
+ 'isoName' => 'Chinese',
+ 'nativeName' => '中文 (Zhōngwén), 汉语, 漢語',
+ ],
+ 'cv' => [
+ 'isoName' => 'Chuvash',
+ 'nativeName' => 'чӑваш чӗлхи',
+ ],
+ 'kw' => [
+ 'isoName' => 'Cornish',
+ 'nativeName' => 'Kernewek',
+ ],
+ 'co' => [
+ 'isoName' => 'Corsican',
+ 'nativeName' => 'corsu, lingua corsa',
+ ],
+ 'cr' => [
+ 'isoName' => 'Cree',
+ 'nativeName' => 'ᓀᐦᐃᔭᐍᐏᐣ',
+ ],
+ 'hr' => [
+ 'isoName' => 'Croatian',
+ 'nativeName' => 'hrvatski jezik',
+ ],
+ 'cs' => [
+ 'isoName' => 'Czech',
+ 'nativeName' => 'čeština, český jazyk',
+ ],
+ 'da' => [
+ 'isoName' => 'Danish',
+ 'nativeName' => 'dansk',
+ ],
+ 'dv' => [
+ 'isoName' => 'Divehi, Dhivehi, Maldivian',
+ 'nativeName' => 'ދިވެހި',
+ ],
+ 'nl' => [
+ 'isoName' => 'Dutch, Flemish',
+ 'nativeName' => 'Nederlands, Vlaams',
+ ],
+ 'dz' => [
+ 'isoName' => 'Dzongkha',
+ 'nativeName' => 'རྫོང་ཁ',
+ ],
+ 'en' => [
+ 'isoName' => 'English',
+ 'nativeName' => 'English',
+ ],
+ 'eo' => [
+ 'isoName' => 'Esperanto',
+ 'nativeName' => 'Esperanto',
+ ],
+ 'et' => [
+ 'isoName' => 'Estonian',
+ 'nativeName' => 'eesti, eesti keel',
+ ],
+ 'ee' => [
+ 'isoName' => 'Ewe',
+ 'nativeName' => 'Eʋegbe',
+ ],
+ 'fo' => [
+ 'isoName' => 'Faroese',
+ 'nativeName' => 'føroyskt',
+ ],
+ 'fj' => [
+ 'isoName' => 'Fijian',
+ 'nativeName' => 'vosa Vakaviti',
+ ],
+ 'fi' => [
+ 'isoName' => 'Finnish',
+ 'nativeName' => 'suomi, suomen kieli',
+ ],
+ 'fr' => [
+ 'isoName' => 'French',
+ 'nativeName' => 'français',
+ ],
+ 'ff' => [
+ 'isoName' => 'Fulah',
+ 'nativeName' => 'Fulfulde, Pulaar, Pular',
+ ],
+ 'gl' => [
+ 'isoName' => 'Galician',
+ 'nativeName' => 'Galego',
+ ],
+ 'ka' => [
+ 'isoName' => 'Georgian',
+ 'nativeName' => 'ქართული',
+ ],
+ 'de' => [
+ 'isoName' => 'German',
+ 'nativeName' => 'Deutsch',
+ ],
+ 'el' => [
+ 'isoName' => 'Greek (modern)',
+ 'nativeName' => 'ελληνικά',
+ ],
+ 'gn' => [
+ 'isoName' => 'Guaraní',
+ 'nativeName' => 'Avañe\'ẽ',
+ ],
+ 'gu' => [
+ 'isoName' => 'Gujarati',
+ 'nativeName' => 'ગુજરાતી',
+ ],
+ 'ht' => [
+ 'isoName' => 'Haitian, Haitian Creole',
+ 'nativeName' => 'Kreyòl ayisyen',
+ ],
+ 'ha' => [
+ 'isoName' => 'Hausa',
+ 'nativeName' => '(Hausa) هَوُسَ',
+ ],
+ 'he' => [
+ 'isoName' => 'Hebrew (modern)',
+ 'nativeName' => 'עברית',
+ ],
+ 'hz' => [
+ 'isoName' => 'Herero',
+ 'nativeName' => 'Otjiherero',
+ ],
+ 'hi' => [
+ 'isoName' => 'Hindi',
+ 'nativeName' => 'हिन्दी, हिंदी',
+ ],
+ 'ho' => [
+ 'isoName' => 'Hiri Motu',
+ 'nativeName' => 'Hiri Motu',
+ ],
+ 'hu' => [
+ 'isoName' => 'Hungarian',
+ 'nativeName' => 'magyar',
+ ],
+ 'ia' => [
+ 'isoName' => 'Interlingua',
+ 'nativeName' => 'Interlingua',
+ ],
+ 'id' => [
+ 'isoName' => 'Indonesian',
+ 'nativeName' => 'Bahasa Indonesia',
+ ],
+ 'ie' => [
+ 'isoName' => 'Interlingue',
+ 'nativeName' => 'Originally called Occidental; then Interlingue after WWII',
+ ],
+ 'ga' => [
+ 'isoName' => 'Irish',
+ 'nativeName' => 'Gaeilge',
+ ],
+ 'ig' => [
+ 'isoName' => 'Igbo',
+ 'nativeName' => 'Asụsụ Igbo',
+ ],
+ 'ik' => [
+ 'isoName' => 'Inupiaq',
+ 'nativeName' => 'Iñupiaq, Iñupiatun',
+ ],
+ 'io' => [
+ 'isoName' => 'Ido',
+ 'nativeName' => 'Ido',
+ ],
+ 'is' => [
+ 'isoName' => 'Icelandic',
+ 'nativeName' => 'Íslenska',
+ ],
+ 'it' => [
+ 'isoName' => 'Italian',
+ 'nativeName' => 'Italiano',
+ ],
+ 'iu' => [
+ 'isoName' => 'Inuktitut',
+ 'nativeName' => 'ᐃᓄᒃᑎᑐᑦ',
+ ],
+ 'ja' => [
+ 'isoName' => 'Japanese',
+ 'nativeName' => '日本語 (にほんご)',
+ ],
+ 'jv' => [
+ 'isoName' => 'Javanese',
+ 'nativeName' => 'ꦧꦱꦗꦮ, Basa Jawa',
+ ],
+ 'kl' => [
+ 'isoName' => 'Kalaallisut, Greenlandic',
+ 'nativeName' => 'kalaallisut, kalaallit oqaasii',
+ ],
+ 'kn' => [
+ 'isoName' => 'Kannada',
+ 'nativeName' => 'ಕನ್ನಡ',
+ ],
+ 'kr' => [
+ 'isoName' => 'Kanuri',
+ 'nativeName' => 'Kanuri',
+ ],
+ 'ks' => [
+ 'isoName' => 'Kashmiri',
+ 'nativeName' => 'कश्मीरी, كشميري',
+ ],
+ 'kk' => [
+ 'isoName' => 'Kazakh',
+ 'nativeName' => 'қазақ тілі',
+ ],
+ 'km' => [
+ 'isoName' => 'Central Khmer',
+ 'nativeName' => 'ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ',
+ ],
+ 'ki' => [
+ 'isoName' => 'Kikuyu, Gikuyu',
+ 'nativeName' => 'Gĩkũyũ',
+ ],
+ 'rw' => [
+ 'isoName' => 'Kinyarwanda',
+ 'nativeName' => 'Ikinyarwanda',
+ ],
+ 'ky' => [
+ 'isoName' => 'Kirghiz, Kyrgyz',
+ 'nativeName' => 'Кыргызча, Кыргыз тили',
+ ],
+ 'kv' => [
+ 'isoName' => 'Komi',
+ 'nativeName' => 'коми кыв',
+ ],
+ 'kg' => [
+ 'isoName' => 'Kongo',
+ 'nativeName' => 'Kikongo',
+ ],
+ 'ko' => [
+ 'isoName' => 'Korean',
+ 'nativeName' => '한국어',
+ ],
+ 'ku' => [
+ 'isoName' => 'Kurdish',
+ 'nativeName' => 'Kurdî, کوردی',
+ ],
+ 'kj' => [
+ 'isoName' => 'Kuanyama, Kwanyama',
+ 'nativeName' => 'Kuanyama',
+ ],
+ 'la' => [
+ 'isoName' => 'Latin',
+ 'nativeName' => 'latine, lingua latina',
+ ],
+ 'lb' => [
+ 'isoName' => 'Luxembourgish, Letzeburgesch',
+ 'nativeName' => 'Lëtzebuergesch',
+ ],
+ 'lg' => [
+ 'isoName' => 'Ganda',
+ 'nativeName' => 'Luganda',
+ ],
+ 'li' => [
+ 'isoName' => 'Limburgan, Limburger, Limburgish',
+ 'nativeName' => 'Limburgs',
+ ],
+ 'ln' => [
+ 'isoName' => 'Lingala',
+ 'nativeName' => 'Lingála',
+ ],
+ 'lo' => [
+ 'isoName' => 'Lao',
+ 'nativeName' => 'ພາສາລາວ',
+ ],
+ 'lt' => [
+ 'isoName' => 'Lithuanian',
+ 'nativeName' => 'lietuvių kalba',
+ ],
+ 'lu' => [
+ 'isoName' => 'Luba-Katanga',
+ 'nativeName' => 'Kiluba',
+ ],
+ 'lv' => [
+ 'isoName' => 'Latvian',
+ 'nativeName' => 'latviešu valoda',
+ ],
+ 'gv' => [
+ 'isoName' => 'Manx',
+ 'nativeName' => 'Gaelg, Gailck',
+ ],
+ 'mk' => [
+ 'isoName' => 'Macedonian',
+ 'nativeName' => 'македонски јазик',
+ ],
+ 'mg' => [
+ 'isoName' => 'Malagasy',
+ 'nativeName' => 'fiteny malagasy',
+ ],
+ 'ms' => [
+ 'isoName' => 'Malay',
+ 'nativeName' => 'Bahasa Melayu, بهاس ملايو',
+ ],
+ 'ml' => [
+ 'isoName' => 'Malayalam',
+ 'nativeName' => 'മലയാളം',
+ ],
+ 'mt' => [
+ 'isoName' => 'Maltese',
+ 'nativeName' => 'Malti',
+ ],
+ 'mi' => [
+ 'isoName' => 'Maori',
+ 'nativeName' => 'te reo Māori',
+ ],
+ 'mr' => [
+ 'isoName' => 'Marathi',
+ 'nativeName' => 'मराठी',
+ ],
+ 'mh' => [
+ 'isoName' => 'Marshallese',
+ 'nativeName' => 'Kajin M̧ajeļ',
+ ],
+ 'mn' => [
+ 'isoName' => 'Mongolian',
+ 'nativeName' => 'Монгол хэл',
+ ],
+ 'na' => [
+ 'isoName' => 'Nauru',
+ 'nativeName' => 'Dorerin Naoero',
+ ],
+ 'nv' => [
+ 'isoName' => 'Navajo, Navaho',
+ 'nativeName' => 'Diné bizaad',
+ ],
+ 'nd' => [
+ 'isoName' => 'North Ndebele',
+ 'nativeName' => 'isiNdebele',
+ ],
+ 'ne' => [
+ 'isoName' => 'Nepali',
+ 'nativeName' => 'नेपाली',
+ ],
+ 'ng' => [
+ 'isoName' => 'Ndonga',
+ 'nativeName' => 'Owambo',
+ ],
+ 'nb' => [
+ 'isoName' => 'Norwegian Bokmål',
+ 'nativeName' => 'Norsk Bokmål',
+ ],
+ 'nn' => [
+ 'isoName' => 'Norwegian Nynorsk',
+ 'nativeName' => 'Norsk Nynorsk',
+ ],
+ 'no' => [
+ 'isoName' => 'Norwegian',
+ 'nativeName' => 'Norsk',
+ ],
+ 'ii' => [
+ 'isoName' => 'Sichuan Yi, Nuosu',
+ 'nativeName' => 'ꆈꌠ꒿ Nuosuhxop',
+ ],
+ 'nr' => [
+ 'isoName' => 'South Ndebele',
+ 'nativeName' => 'isiNdebele',
+ ],
+ 'oc' => [
+ 'isoName' => 'Occitan',
+ 'nativeName' => 'occitan, lenga d\'òc',
+ ],
+ 'oj' => [
+ 'isoName' => 'Ojibwa',
+ 'nativeName' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ',
+ ],
+ 'cu' => [
+ 'isoName' => 'Church Slavic, Church Slavonic, Old Church Slavonic, Old Slavonic, Old Bulgarian',
+ 'nativeName' => 'ѩзыкъ словѣньскъ',
+ ],
+ 'om' => [
+ 'isoName' => 'Oromo',
+ 'nativeName' => 'Afaan Oromoo',
+ ],
+ 'or' => [
+ 'isoName' => 'Oriya',
+ 'nativeName' => 'ଓଡ଼ିଆ',
+ ],
+ 'os' => [
+ 'isoName' => 'Ossetian, Ossetic',
+ 'nativeName' => 'ирон æвзаг',
+ ],
+ 'pa' => [
+ 'isoName' => 'Panjabi, Punjabi',
+ 'nativeName' => 'ਪੰਜਾਬੀ',
+ ],
+ 'pi' => [
+ 'isoName' => 'Pali',
+ 'nativeName' => 'पाऴि',
+ ],
+ 'fa' => [
+ 'isoName' => 'Persian',
+ 'nativeName' => 'فارسی',
+ ],
+ 'pl' => [
+ 'isoName' => 'Polish',
+ 'nativeName' => 'język polski, polszczyzna',
+ ],
+ 'ps' => [
+ 'isoName' => 'Pashto, Pushto',
+ 'nativeName' => 'پښتو',
+ ],
+ 'pt' => [
+ 'isoName' => 'Portuguese',
+ 'nativeName' => 'Português',
+ ],
+ 'qu' => [
+ 'isoName' => 'Quechua',
+ 'nativeName' => 'Runa Simi, Kichwa',
+ ],
+ 'rm' => [
+ 'isoName' => 'Romansh',
+ 'nativeName' => 'Rumantsch Grischun',
+ ],
+ 'rn' => [
+ 'isoName' => 'Rundi',
+ 'nativeName' => 'Ikirundi',
+ ],
+ 'ro' => [
+ 'isoName' => 'Romanian, Moldavian, Moldovan',
+ 'nativeName' => 'Română',
+ ],
+ 'ru' => [
+ 'isoName' => 'Russian',
+ 'nativeName' => 'русский',
+ ],
+ 'sa' => [
+ 'isoName' => 'Sanskrit',
+ 'nativeName' => 'संस्कृतम्',
+ ],
+ 'sc' => [
+ 'isoName' => 'Sardinian',
+ 'nativeName' => 'sardu',
+ ],
+ 'sd' => [
+ 'isoName' => 'Sindhi',
+ 'nativeName' => 'सिन्धी, سنڌي، سندھی',
+ ],
+ 'se' => [
+ 'isoName' => 'Northern Sami',
+ 'nativeName' => 'Davvisámegiella',
+ ],
+ 'sm' => [
+ 'isoName' => 'Samoan',
+ 'nativeName' => 'gagana fa\'a Samoa',
+ ],
+ 'sg' => [
+ 'isoName' => 'Sango',
+ 'nativeName' => 'yângâ tî sängö',
+ ],
+ 'sr' => [
+ 'isoName' => 'Serbian',
+ 'nativeName' => 'српски језик',
+ ],
+ 'gd' => [
+ 'isoName' => 'Gaelic, Scottish Gaelic',
+ 'nativeName' => 'Gàidhlig',
+ ],
+ 'sn' => [
+ 'isoName' => 'Shona',
+ 'nativeName' => 'chiShona',
+ ],
+ 'si' => [
+ 'isoName' => 'Sinhala, Sinhalese',
+ 'nativeName' => 'සිංහල',
+ ],
+ 'sk' => [
+ 'isoName' => 'Slovak',
+ 'nativeName' => 'Slovenčina, Slovenský Jazyk',
+ ],
+ 'sl' => [
+ 'isoName' => 'Slovene',
+ 'nativeName' => 'Slovenski Jezik, Slovenščina',
+ ],
+ 'so' => [
+ 'isoName' => 'Somali',
+ 'nativeName' => 'Soomaaliga, af Soomaali',
+ ],
+ 'st' => [
+ 'isoName' => 'Southern Sotho',
+ 'nativeName' => 'Sesotho',
+ ],
+ 'es' => [
+ 'isoName' => 'Spanish, Castilian',
+ 'nativeName' => 'Español',
+ ],
+ 'su' => [
+ 'isoName' => 'Sundanese',
+ 'nativeName' => 'Basa Sunda',
+ ],
+ 'sw' => [
+ 'isoName' => 'Swahili',
+ 'nativeName' => 'Kiswahili',
+ ],
+ 'ss' => [
+ 'isoName' => 'Swati',
+ 'nativeName' => 'SiSwati',
+ ],
+ 'sv' => [
+ 'isoName' => 'Swedish',
+ 'nativeName' => 'Svenska',
+ ],
+ 'ta' => [
+ 'isoName' => 'Tamil',
+ 'nativeName' => 'தமிழ்',
+ ],
+ 'te' => [
+ 'isoName' => 'Telugu',
+ 'nativeName' => 'తెలుగు',
+ ],
+ 'tg' => [
+ 'isoName' => 'Tajik',
+ 'nativeName' => 'тоҷикӣ, toçikī, تاجیکی',
+ ],
+ 'th' => [
+ 'isoName' => 'Thai',
+ 'nativeName' => 'ไทย',
+ ],
+ 'ti' => [
+ 'isoName' => 'Tigrinya',
+ 'nativeName' => 'ትግርኛ',
+ ],
+ 'bo' => [
+ 'isoName' => 'Tibetan',
+ 'nativeName' => 'བོད་ཡིག',
+ ],
+ 'tk' => [
+ 'isoName' => 'Turkmen',
+ 'nativeName' => 'Türkmen, Түркмен',
+ ],
+ 'tl' => [
+ 'isoName' => 'Tagalog',
+ 'nativeName' => 'Wikang Tagalog',
+ ],
+ 'tn' => [
+ 'isoName' => 'Tswana',
+ 'nativeName' => 'Setswana',
+ ],
+ 'to' => [
+ 'isoName' => 'Tongan (Tonga Islands)',
+ 'nativeName' => 'Faka Tonga',
+ ],
+ 'tr' => [
+ 'isoName' => 'Turkish',
+ 'nativeName' => 'Türkçe',
+ ],
+ 'ts' => [
+ 'isoName' => 'Tsonga',
+ 'nativeName' => 'Xitsonga',
+ ],
+ 'tt' => [
+ 'isoName' => 'Tatar',
+ 'nativeName' => 'татар теле, tatar tele',
+ ],
+ 'tw' => [
+ 'isoName' => 'Twi',
+ 'nativeName' => 'Twi',
+ ],
+ 'ty' => [
+ 'isoName' => 'Tahitian',
+ 'nativeName' => 'Reo Tahiti',
+ ],
+ 'ug' => [
+ 'isoName' => 'Uighur, Uyghur',
+ 'nativeName' => 'Uyƣurqə, ئۇيغۇرچ',
+ ],
+ 'uk' => [
+ 'isoName' => 'Ukrainian',
+ 'nativeName' => 'Українська',
+ ],
+ 'ur' => [
+ 'isoName' => 'Urdu',
+ 'nativeName' => 'اردو',
+ ],
+ 'uz' => [
+ 'isoName' => 'Uzbek',
+ 'nativeName' => 'Oʻzbek, Ўзбек, أۇزبېك',
+ ],
+ 've' => [
+ 'isoName' => 'Venda',
+ 'nativeName' => 'Tshivenḓa',
+ ],
+ 'vi' => [
+ 'isoName' => 'Vietnamese',
+ 'nativeName' => 'Tiếng Việt',
+ ],
+ 'vo' => [
+ 'isoName' => 'Volapük',
+ 'nativeName' => 'Volapük',
+ ],
+ 'wa' => [
+ 'isoName' => 'Walloon',
+ 'nativeName' => 'Walon',
+ ],
+ 'cy' => [
+ 'isoName' => 'Welsh',
+ 'nativeName' => 'Cymraeg',
+ ],
+ 'wo' => [
+ 'isoName' => 'Wolof',
+ 'nativeName' => 'Wollof',
+ ],
+ 'fy' => [
+ 'isoName' => 'Western Frisian',
+ 'nativeName' => 'Frysk',
+ ],
+ 'xh' => [
+ 'isoName' => 'Xhosa',
+ 'nativeName' => 'isiXhosa',
+ ],
+ 'yi' => [
+ 'isoName' => 'Yiddish',
+ 'nativeName' => 'ייִדיש',
+ ],
+ 'yo' => [
+ 'isoName' => 'Yoruba',
+ 'nativeName' => 'Yorùbá',
+ ],
+ 'za' => [
+ 'isoName' => 'Zhuang, Chuang',
+ 'nativeName' => 'Saɯ cueŋƅ, Saw cuengh',
+ ],
+ 'zu' => [
+ 'isoName' => 'Zulu',
+ 'nativeName' => 'isiZulu',
+ ],
+ /*
+ * Add ISO 639-3 languages available in Carbon
+ */
+ 'agq' => [
+ 'isoName' => 'Aghem',
+ 'nativeName' => 'Aghem',
+ ],
+ 'agr' => [
+ 'isoName' => 'Aguaruna',
+ 'nativeName' => 'Aguaruna',
+ ],
+ 'anp' => [
+ 'isoName' => 'Angika',
+ 'nativeName' => 'Angika',
+ ],
+ 'asa' => [
+ 'isoName' => 'Asu',
+ 'nativeName' => 'Asu',
+ ],
+ 'ast' => [
+ 'isoName' => 'Asturian',
+ 'nativeName' => 'Asturian',
+ ],
+ 'ayc' => [
+ 'isoName' => 'Southern Aymara',
+ 'nativeName' => 'Southern Aymara',
+ ],
+ 'bas' => [
+ 'isoName' => 'Basaa',
+ 'nativeName' => 'Basaa',
+ ],
+ 'bem' => [
+ 'isoName' => 'Bemba',
+ 'nativeName' => 'Bemba',
+ ],
+ 'bez' => [
+ 'isoName' => 'Bena',
+ 'nativeName' => 'Bena',
+ ],
+ 'bhb' => [
+ 'isoName' => 'Bhili',
+ 'nativeName' => 'Bhili',
+ ],
+ 'bho' => [
+ 'isoName' => 'Bhojpuri',
+ 'nativeName' => 'Bhojpuri',
+ ],
+ 'brx' => [
+ 'isoName' => 'Bodo',
+ 'nativeName' => 'Bodo',
+ ],
+ 'byn' => [
+ 'isoName' => 'Bilin',
+ 'nativeName' => 'Bilin',
+ ],
+ 'ccp' => [
+ 'isoName' => 'Chakma',
+ 'nativeName' => 'Chakma',
+ ],
+ 'cgg' => [
+ 'isoName' => 'Chiga',
+ 'nativeName' => 'Chiga',
+ ],
+ 'chr' => [
+ 'isoName' => 'Cherokee',
+ 'nativeName' => 'Cherokee',
+ ],
+ 'cmn' => [
+ 'isoName' => 'Chinese',
+ 'nativeName' => 'Chinese',
+ ],
+ 'crh' => [
+ 'isoName' => 'Crimean Turkish',
+ 'nativeName' => 'Crimean Turkish',
+ ],
+ 'csb' => [
+ 'isoName' => 'Kashubian',
+ 'nativeName' => 'Kashubian',
+ ],
+ 'dav' => [
+ 'isoName' => 'Taita',
+ 'nativeName' => 'Taita',
+ ],
+ 'dje' => [
+ 'isoName' => 'Zarma',
+ 'nativeName' => 'Zarma',
+ ],
+ 'doi' => [
+ 'isoName' => 'Dogri (macrolanguage)',
+ 'nativeName' => 'Dogri (macrolanguage)',
+ ],
+ 'dsb' => [
+ 'isoName' => 'Lower Sorbian',
+ 'nativeName' => 'Lower Sorbian',
+ ],
+ 'dua' => [
+ 'isoName' => 'Duala',
+ 'nativeName' => 'Duala',
+ ],
+ 'dyo' => [
+ 'isoName' => 'Jola-Fonyi',
+ 'nativeName' => 'Jola-Fonyi',
+ ],
+ 'ebu' => [
+ 'isoName' => 'Embu',
+ 'nativeName' => 'Embu',
+ ],
+ 'ewo' => [
+ 'isoName' => 'Ewondo',
+ 'nativeName' => 'Ewondo',
+ ],
+ 'fil' => [
+ 'isoName' => 'Filipino',
+ 'nativeName' => 'Filipino',
+ ],
+ 'fur' => [
+ 'isoName' => 'Friulian',
+ 'nativeName' => 'Friulian',
+ ],
+ 'gez' => [
+ 'isoName' => 'Geez',
+ 'nativeName' => 'Geez',
+ ],
+ 'gom' => [
+ 'isoName' => 'Konkani, Goan',
+ 'nativeName' => 'ಕೊಂಕಣಿ',
+ ],
+ 'gsw' => [
+ 'isoName' => 'Swiss German',
+ 'nativeName' => 'Swiss German',
+ ],
+ 'guz' => [
+ 'isoName' => 'Gusii',
+ 'nativeName' => 'Gusii',
+ ],
+ 'hak' => [
+ 'isoName' => 'Hakka Chinese',
+ 'nativeName' => 'Hakka Chinese',
+ ],
+ 'haw' => [
+ 'isoName' => 'Hawaiian',
+ 'nativeName' => 'Hawaiian',
+ ],
+ 'hif' => [
+ 'isoName' => 'Fiji Hindi',
+ 'nativeName' => 'Fiji Hindi',
+ ],
+ 'hne' => [
+ 'isoName' => 'Chhattisgarhi',
+ 'nativeName' => 'Chhattisgarhi',
+ ],
+ 'hsb' => [
+ 'isoName' => 'Upper Sorbian',
+ 'nativeName' => 'Upper Sorbian',
+ ],
+ 'jgo' => [
+ 'isoName' => 'Ngomba',
+ 'nativeName' => 'Ngomba',
+ ],
+ 'jmc' => [
+ 'isoName' => 'Machame',
+ 'nativeName' => 'Machame',
+ ],
+ 'kab' => [
+ 'isoName' => 'Kabyle',
+ 'nativeName' => 'Kabyle',
+ ],
+ 'kam' => [
+ 'isoName' => 'Kamba',
+ 'nativeName' => 'Kamba',
+ ],
+ 'kde' => [
+ 'isoName' => 'Makonde',
+ 'nativeName' => 'Makonde',
+ ],
+ 'kea' => [
+ 'isoName' => 'Kabuverdianu',
+ 'nativeName' => 'Kabuverdianu',
+ ],
+ 'khq' => [
+ 'isoName' => 'Koyra Chiini',
+ 'nativeName' => 'Koyra Chiini',
+ ],
+ 'kkj' => [
+ 'isoName' => 'Kako',
+ 'nativeName' => 'Kako',
+ ],
+ 'kln' => [
+ 'isoName' => 'Kalenjin',
+ 'nativeName' => 'Kalenjin',
+ ],
+ 'kok' => [
+ 'isoName' => 'Konkani',
+ 'nativeName' => 'Konkani',
+ ],
+ 'ksb' => [
+ 'isoName' => 'Shambala',
+ 'nativeName' => 'Shambala',
+ ],
+ 'ksf' => [
+ 'isoName' => 'Bafia',
+ 'nativeName' => 'Bafia',
+ ],
+ 'ksh' => [
+ 'isoName' => 'Colognian',
+ 'nativeName' => 'Colognian',
+ ],
+ 'lag' => [
+ 'isoName' => 'Langi',
+ 'nativeName' => 'Langi',
+ ],
+ 'lij' => [
+ 'isoName' => 'Ligurian',
+ 'nativeName' => 'Ligurian',
+ ],
+ 'lkt' => [
+ 'isoName' => 'Lakota',
+ 'nativeName' => 'Lakota',
+ ],
+ 'lrc' => [
+ 'isoName' => 'Northern Luri',
+ 'nativeName' => 'Northern Luri',
+ ],
+ 'luo' => [
+ 'isoName' => 'Luo',
+ 'nativeName' => 'Luo',
+ ],
+ 'luy' => [
+ 'isoName' => 'Luyia',
+ 'nativeName' => 'Luyia',
+ ],
+ 'lzh' => [
+ 'isoName' => 'Literary Chinese',
+ 'nativeName' => 'Literary Chinese',
+ ],
+ 'mag' => [
+ 'isoName' => 'Magahi',
+ 'nativeName' => 'Magahi',
+ ],
+ 'mai' => [
+ 'isoName' => 'Maithili',
+ 'nativeName' => 'Maithili',
+ ],
+ 'mas' => [
+ 'isoName' => 'Masai',
+ 'nativeName' => 'Masai',
+ ],
+ 'mer' => [
+ 'isoName' => 'Meru',
+ 'nativeName' => 'Meru',
+ ],
+ 'mfe' => [
+ 'isoName' => 'Morisyen',
+ 'nativeName' => 'Morisyen',
+ ],
+ 'mgh' => [
+ 'isoName' => 'Makhuwa-Meetto',
+ 'nativeName' => 'Makhuwa-Meetto',
+ ],
+ 'mgo' => [
+ 'isoName' => 'Metaʼ',
+ 'nativeName' => 'Metaʼ',
+ ],
+ 'mhr' => [
+ 'isoName' => 'Eastern Mari',
+ 'nativeName' => 'Eastern Mari',
+ ],
+ 'miq' => [
+ 'isoName' => 'Mískito',
+ 'nativeName' => 'Mískito',
+ ],
+ 'mjw' => [
+ 'isoName' => 'Karbi',
+ 'nativeName' => 'Karbi',
+ ],
+ 'mni' => [
+ 'isoName' => 'Manipuri',
+ 'nativeName' => 'Manipuri',
+ ],
+ 'mua' => [
+ 'isoName' => 'Mundang',
+ 'nativeName' => 'Mundang',
+ ],
+ 'mzn' => [
+ 'isoName' => 'Mazanderani',
+ 'nativeName' => 'Mazanderani',
+ ],
+ 'nan' => [
+ 'isoName' => 'Min Nan Chinese',
+ 'nativeName' => 'Min Nan Chinese',
+ ],
+ 'naq' => [
+ 'isoName' => 'Nama',
+ 'nativeName' => 'Nama',
+ ],
+ 'nds' => [
+ 'isoName' => 'Low German',
+ 'nativeName' => 'Low German',
+ ],
+ 'nhn' => [
+ 'isoName' => 'Central Nahuatl',
+ 'nativeName' => 'Central Nahuatl',
+ ],
+ 'niu' => [
+ 'isoName' => 'Niuean',
+ 'nativeName' => 'Niuean',
+ ],
+ 'nmg' => [
+ 'isoName' => 'Kwasio',
+ 'nativeName' => 'Kwasio',
+ ],
+ 'nnh' => [
+ 'isoName' => 'Ngiemboon',
+ 'nativeName' => 'Ngiemboon',
+ ],
+ 'nso' => [
+ 'isoName' => 'Northern Sotho',
+ 'nativeName' => 'Northern Sotho',
+ ],
+ 'nus' => [
+ 'isoName' => 'Nuer',
+ 'nativeName' => 'Nuer',
+ ],
+ 'nyn' => [
+ 'isoName' => 'Nyankole',
+ 'nativeName' => 'Nyankole',
+ ],
+ 'pap' => [
+ 'isoName' => 'Papiamento',
+ 'nativeName' => 'Papiamento',
+ ],
+ 'prg' => [
+ 'isoName' => 'Prussian',
+ 'nativeName' => 'Prussian',
+ ],
+ 'quz' => [
+ 'isoName' => 'Cusco Quechua',
+ 'nativeName' => 'Cusco Quechua',
+ ],
+ 'raj' => [
+ 'isoName' => 'Rajasthani',
+ 'nativeName' => 'Rajasthani',
+ ],
+ 'rof' => [
+ 'isoName' => 'Rombo',
+ 'nativeName' => 'Rombo',
+ ],
+ 'rwk' => [
+ 'isoName' => 'Rwa',
+ 'nativeName' => 'Rwa',
+ ],
+ 'sah' => [
+ 'isoName' => 'Sakha',
+ 'nativeName' => 'Sakha',
+ ],
+ 'saq' => [
+ 'isoName' => 'Samburu',
+ 'nativeName' => 'Samburu',
+ ],
+ 'sat' => [
+ 'isoName' => 'Santali',
+ 'nativeName' => 'Santali',
+ ],
+ 'sbp' => [
+ 'isoName' => 'Sangu',
+ 'nativeName' => 'Sangu',
+ ],
+ 'scr' => [
+ 'isoName' => 'Serbo Croatian',
+ 'nativeName' => 'Serbo Croatian',
+ ],
+ 'seh' => [
+ 'isoName' => 'Sena',
+ 'nativeName' => 'Sena',
+ ],
+ 'ses' => [
+ 'isoName' => 'Koyraboro Senni',
+ 'nativeName' => 'Koyraboro Senni',
+ ],
+ 'sgs' => [
+ 'isoName' => 'Samogitian',
+ 'nativeName' => 'Samogitian',
+ ],
+ 'shi' => [
+ 'isoName' => 'Tachelhit',
+ 'nativeName' => 'Tachelhit',
+ ],
+ 'shn' => [
+ 'isoName' => 'Shan',
+ 'nativeName' => 'Shan',
+ ],
+ 'shs' => [
+ 'isoName' => 'Shuswap',
+ 'nativeName' => 'Shuswap',
+ ],
+ 'sid' => [
+ 'isoName' => 'Sidamo',
+ 'nativeName' => 'Sidamo',
+ ],
+ 'smn' => [
+ 'isoName' => 'Inari Sami',
+ 'nativeName' => 'Inari Sami',
+ ],
+ 'szl' => [
+ 'isoName' => 'Silesian',
+ 'nativeName' => 'Silesian',
+ ],
+ 'tcy' => [
+ 'isoName' => 'Tulu',
+ 'nativeName' => 'Tulu',
+ ],
+ 'teo' => [
+ 'isoName' => 'Teso',
+ 'nativeName' => 'Teso',
+ ],
+ 'tet' => [
+ 'isoName' => 'Tetum',
+ 'nativeName' => 'Tetum',
+ ],
+ 'the' => [
+ 'isoName' => 'Chitwania Tharu',
+ 'nativeName' => 'Chitwania Tharu',
+ ],
+ 'tig' => [
+ 'isoName' => 'Tigre',
+ 'nativeName' => 'Tigre',
+ ],
+ 'tlh' => [
+ 'isoName' => 'Klingon',
+ 'nativeName' => 'tlhIngan Hol',
+ ],
+ 'tpi' => [
+ 'isoName' => 'Tok Pisin',
+ 'nativeName' => 'Tok Pisin',
+ ],
+ 'twq' => [
+ 'isoName' => 'Tasawaq',
+ 'nativeName' => 'Tasawaq',
+ ],
+ 'tzl' => [
+ 'isoName' => 'Talossan',
+ 'nativeName' => 'Talossan',
+ ],
+ 'tzm' => [
+ 'isoName' => 'Tamazight, Central Atlas',
+ 'nativeName' => 'ⵜⵎⴰⵣⵉⵖⵜ',
+ ],
+ 'unm' => [
+ 'isoName' => 'Unami',
+ 'nativeName' => 'Unami',
+ ],
+ 'vai' => [
+ 'isoName' => 'Vai',
+ 'nativeName' => 'Vai',
+ ],
+ 'vun' => [
+ 'isoName' => 'Vunjo',
+ 'nativeName' => 'Vunjo',
+ ],
+ 'wae' => [
+ 'isoName' => 'Walser',
+ 'nativeName' => 'Walser',
+ ],
+ 'wal' => [
+ 'isoName' => 'Wolaytta',
+ 'nativeName' => 'Wolaytta',
+ ],
+ 'xog' => [
+ 'isoName' => 'Soga',
+ 'nativeName' => 'Soga',
+ ],
+ 'yav' => [
+ 'isoName' => 'Yangben',
+ 'nativeName' => 'Yangben',
+ ],
+ 'yue' => [
+ 'isoName' => 'Cantonese',
+ 'nativeName' => 'Cantonese',
+ ],
+ 'yuw' => [
+ 'isoName' => 'Yau (Morobe Province)',
+ 'nativeName' => 'Yau (Morobe Province)',
+ ],
+ 'zgh' => [
+ 'isoName' => 'Standard Moroccan Tamazight',
+ 'nativeName' => 'Standard Moroccan Tamazight',
+ ],
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/List/regions.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/List/regions.php
new file mode 100644
index 0000000..8ab8a9e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/List/regions.php
@@ -0,0 +1,265 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * ISO 3166-2
+ */
+return [
+ 'AD' => 'Andorra',
+ 'AE' => 'United Arab Emirates',
+ 'AF' => 'Afghanistan',
+ 'AG' => 'Antigua and Barbuda',
+ 'AI' => 'Anguilla',
+ 'AL' => 'Albania',
+ 'AM' => 'Armenia',
+ 'AO' => 'Angola',
+ 'AQ' => 'Antarctica',
+ 'AR' => 'Argentina',
+ 'AS' => 'American Samoa',
+ 'AT' => 'Austria',
+ 'AU' => 'Australia',
+ 'AW' => 'Aruba',
+ 'AX' => 'Åland Islands',
+ 'AZ' => 'Azerbaijan',
+ 'BA' => 'Bosnia and Herzegovina',
+ 'BB' => 'Barbados',
+ 'BD' => 'Bangladesh',
+ 'BE' => 'Belgium',
+ 'BF' => 'Burkina Faso',
+ 'BG' => 'Bulgaria',
+ 'BH' => 'Bahrain',
+ 'BI' => 'Burundi',
+ 'BJ' => 'Benin',
+ 'BL' => 'Saint Barthélemy',
+ 'BM' => 'Bermuda',
+ 'BN' => 'Brunei Darussalam',
+ 'BO' => 'Bolivia (Plurinational State of)',
+ 'BQ' => 'Bonaire, Sint Eustatius and Saba',
+ 'BR' => 'Brazil',
+ 'BS' => 'Bahamas',
+ 'BT' => 'Bhutan',
+ 'BV' => 'Bouvet Island',
+ 'BW' => 'Botswana',
+ 'BY' => 'Belarus',
+ 'BZ' => 'Belize',
+ 'CA' => 'Canada',
+ 'CC' => 'Cocos (Keeling) Islands',
+ 'CD' => 'Congo, Democratic Republic of the',
+ 'CF' => 'Central African Republic',
+ 'CG' => 'Congo',
+ 'CH' => 'Switzerland',
+ 'CI' => 'Côte d\'Ivoire',
+ 'CK' => 'Cook Islands',
+ 'CL' => 'Chile',
+ 'CM' => 'Cameroon',
+ 'CN' => 'China',
+ 'CO' => 'Colombia',
+ 'CR' => 'Costa Rica',
+ 'CU' => 'Cuba',
+ 'CV' => 'Cabo Verde',
+ 'CW' => 'Curaçao',
+ 'CX' => 'Christmas Island',
+ 'CY' => 'Cyprus',
+ 'CZ' => 'Czechia',
+ 'DE' => 'Germany',
+ 'DJ' => 'Djibouti',
+ 'DK' => 'Denmark',
+ 'DM' => 'Dominica',
+ 'DO' => 'Dominican Republic',
+ 'DZ' => 'Algeria',
+ 'EC' => 'Ecuador',
+ 'EE' => 'Estonia',
+ 'EG' => 'Egypt',
+ 'EH' => 'Western Sahara',
+ 'ER' => 'Eritrea',
+ 'ES' => 'Spain',
+ 'ET' => 'Ethiopia',
+ 'FI' => 'Finland',
+ 'FJ' => 'Fiji',
+ 'FK' => 'Falkland Islands (Malvinas)',
+ 'FM' => 'Micronesia (Federated States of)',
+ 'FO' => 'Faroe Islands',
+ 'FR' => 'France',
+ 'GA' => 'Gabon',
+ 'GB' => 'United Kingdom of Great Britain and Northern Ireland',
+ 'GD' => 'Grenada',
+ 'GE' => 'Georgia',
+ 'GF' => 'French Guiana',
+ 'GG' => 'Guernsey',
+ 'GH' => 'Ghana',
+ 'GI' => 'Gibraltar',
+ 'GL' => 'Greenland',
+ 'GM' => 'Gambia',
+ 'GN' => 'Guinea',
+ 'GP' => 'Guadeloupe',
+ 'GQ' => 'Equatorial Guinea',
+ 'GR' => 'Greece',
+ 'GS' => 'South Georgia and the South Sandwich Islands',
+ 'GT' => 'Guatemala',
+ 'GU' => 'Guam',
+ 'GW' => 'Guinea-Bissau',
+ 'GY' => 'Guyana',
+ 'HK' => 'Hong Kong',
+ 'HM' => 'Heard Island and McDonald Islands',
+ 'HN' => 'Honduras',
+ 'HR' => 'Croatia',
+ 'HT' => 'Haiti',
+ 'HU' => 'Hungary',
+ 'ID' => 'Indonesia',
+ 'IE' => 'Ireland',
+ 'IL' => 'Israel',
+ 'IM' => 'Isle of Man',
+ 'IN' => 'India',
+ 'IO' => 'British Indian Ocean Territory',
+ 'IQ' => 'Iraq',
+ 'IR' => 'Iran (Islamic Republic of)',
+ 'IS' => 'Iceland',
+ 'IT' => 'Italy',
+ 'JE' => 'Jersey',
+ 'JM' => 'Jamaica',
+ 'JO' => 'Jordan',
+ 'JP' => 'Japan',
+ 'KE' => 'Kenya',
+ 'KG' => 'Kyrgyzstan',
+ 'KH' => 'Cambodia',
+ 'KI' => 'Kiribati',
+ 'KM' => 'Comoros',
+ 'KN' => 'Saint Kitts and Nevis',
+ 'KP' => 'Korea (Democratic People\'s Republic of)',
+ 'KR' => 'Korea, Republic of',
+ 'KW' => 'Kuwait',
+ 'KY' => 'Cayman Islands',
+ 'KZ' => 'Kazakhstan',
+ 'LA' => 'Lao People\'s Democratic Republic',
+ 'LB' => 'Lebanon',
+ 'LC' => 'Saint Lucia',
+ 'LI' => 'Liechtenstein',
+ 'LK' => 'Sri Lanka',
+ 'LR' => 'Liberia',
+ 'LS' => 'Lesotho',
+ 'LT' => 'Lithuania',
+ 'LU' => 'Luxembourg',
+ 'LV' => 'Latvia',
+ 'LY' => 'Libya',
+ 'MA' => 'Morocco',
+ 'MC' => 'Monaco',
+ 'MD' => 'Moldova, Republic of',
+ 'ME' => 'Montenegro',
+ 'MF' => 'Saint Martin (French part)',
+ 'MG' => 'Madagascar',
+ 'MH' => 'Marshall Islands',
+ 'MK' => 'Macedonia, the former Yugoslav Republic of',
+ 'ML' => 'Mali',
+ 'MM' => 'Myanmar',
+ 'MN' => 'Mongolia',
+ 'MO' => 'Macao',
+ 'MP' => 'Northern Mariana Islands',
+ 'MQ' => 'Martinique',
+ 'MR' => 'Mauritania',
+ 'MS' => 'Montserrat',
+ 'MT' => 'Malta',
+ 'MU' => 'Mauritius',
+ 'MV' => 'Maldives',
+ 'MW' => 'Malawi',
+ 'MX' => 'Mexico',
+ 'MY' => 'Malaysia',
+ 'MZ' => 'Mozambique',
+ 'NA' => 'Namibia',
+ 'NC' => 'New Caledonia',
+ 'NE' => 'Niger',
+ 'NF' => 'Norfolk Island',
+ 'NG' => 'Nigeria',
+ 'NI' => 'Nicaragua',
+ 'NL' => 'Netherlands',
+ 'NO' => 'Norway',
+ 'NP' => 'Nepal',
+ 'NR' => 'Nauru',
+ 'NU' => 'Niue',
+ 'NZ' => 'New Zealand',
+ 'OM' => 'Oman',
+ 'PA' => 'Panama',
+ 'PE' => 'Peru',
+ 'PF' => 'French Polynesia',
+ 'PG' => 'Papua New Guinea',
+ 'PH' => 'Philippines',
+ 'PK' => 'Pakistan',
+ 'PL' => 'Poland',
+ 'PM' => 'Saint Pierre and Miquelon',
+ 'PN' => 'Pitcairn',
+ 'PR' => 'Puerto Rico',
+ 'PS' => 'Palestine, State of',
+ 'PT' => 'Portugal',
+ 'PW' => 'Palau',
+ 'PY' => 'Paraguay',
+ 'QA' => 'Qatar',
+ 'RE' => 'Réunion',
+ 'RO' => 'Romania',
+ 'RS' => 'Serbia',
+ 'RU' => 'Russian Federation',
+ 'RW' => 'Rwanda',
+ 'SA' => 'Saudi Arabia',
+ 'SB' => 'Solomon Islands',
+ 'SC' => 'Seychelles',
+ 'SD' => 'Sudan',
+ 'SE' => 'Sweden',
+ 'SG' => 'Singapore',
+ 'SH' => 'Saint Helena, Ascension and Tristan da Cunha',
+ 'SI' => 'Slovenia',
+ 'SJ' => 'Svalbard and Jan Mayen',
+ 'SK' => 'Slovakia',
+ 'SL' => 'Sierra Leone',
+ 'SM' => 'San Marino',
+ 'SN' => 'Senegal',
+ 'SO' => 'Somalia',
+ 'SR' => 'Suriname',
+ 'SS' => 'South Sudan',
+ 'ST' => 'Sao Tome and Principe',
+ 'SV' => 'El Salvador',
+ 'SX' => 'Sint Maarten (Dutch part)',
+ 'SY' => 'Syrian Arab Republic',
+ 'SZ' => 'Eswatini',
+ 'TC' => 'Turks and Caicos Islands',
+ 'TD' => 'Chad',
+ 'TF' => 'French Southern Territories',
+ 'TG' => 'Togo',
+ 'TH' => 'Thailand',
+ 'TJ' => 'Tajikistan',
+ 'TK' => 'Tokelau',
+ 'TL' => 'Timor-Leste',
+ 'TM' => 'Turkmenistan',
+ 'TN' => 'Tunisia',
+ 'TO' => 'Tonga',
+ 'TR' => 'Turkey',
+ 'TT' => 'Trinidad and Tobago',
+ 'TV' => 'Tuvalu',
+ 'TW' => 'Taiwan, Province of China',
+ 'TZ' => 'Tanzania, United Republic of',
+ 'UA' => 'Ukraine',
+ 'UG' => 'Uganda',
+ 'UM' => 'United States Minor Outlying Islands',
+ 'US' => 'United States of America',
+ 'UY' => 'Uruguay',
+ 'UZ' => 'Uzbekistan',
+ 'VA' => 'Holy See',
+ 'VC' => 'Saint Vincent and the Grenadines',
+ 'VE' => 'Venezuela (Bolivarian Republic of)',
+ 'VG' => 'Virgin Islands (British)',
+ 'VI' => 'Virgin Islands (U.S.)',
+ 'VN' => 'Viet Nam',
+ 'VU' => 'Vanuatu',
+ 'WF' => 'Wallis and Futuna',
+ 'WS' => 'Samoa',
+ 'YE' => 'Yemen',
+ 'YT' => 'Mayotte',
+ 'ZA' => 'South Africa',
+ 'ZM' => 'Zambia',
+ 'ZW' => 'Zimbabwe',
+];
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/PHPStan/Macro.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/PHPStan/Macro.php
new file mode 100644
index 0000000..7dab190
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/PHPStan/Macro.php
@@ -0,0 +1,233 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Carbon\PHPStan;
+
+use Closure;
+use PHPStan\Reflection\Php\BuiltinMethodReflection;
+use PHPStan\TrinaryLogic;
+use ReflectionClass;
+use ReflectionFunction;
+use ReflectionMethod;
+use ReflectionParameter;
+use ReflectionType;
+use stdClass;
+use Throwable;
+
+final class Macro implements BuiltinMethodReflection
+{
+ /**
+ * The class name.
+ *
+ * @var class-string
+ */
+ private $className;
+
+ /**
+ * The method name.
+ *
+ * @var string
+ */
+ private $methodName;
+
+ /**
+ * The reflection function/method.
+ *
+ * @var ReflectionFunction|ReflectionMethod
+ */
+ private $reflectionFunction;
+
+ /**
+ * The parameters.
+ *
+ * @var ReflectionParameter[]
+ */
+ private $parameters;
+
+ /**
+ * The is static.
+ *
+ * @var bool
+ */
+ private $static = false;
+
+ /**
+ * Macro constructor.
+ *
+ * @param string $className
+ * @phpstan-param class-string $className
+ *
+ * @param string $methodName
+ * @param callable $macro
+ */
+ public function __construct(string $className, string $methodName, $macro)
+ {
+ $this->className = $className;
+ $this->methodName = $methodName;
+ $this->reflectionFunction = \is_array($macro)
+ ? new ReflectionMethod($macro[0], $macro[1])
+ : new ReflectionFunction($macro);
+ $this->parameters = $this->reflectionFunction->getParameters();
+
+ if ($this->reflectionFunction->isClosure()) {
+ try {
+ /** @var Closure $closure */
+ $closure = $this->reflectionFunction->getClosure();
+ $boundClosure = Closure::bind($closure, new stdClass);
+ $this->static = (!$boundClosure || (new ReflectionFunction($boundClosure))->getClosureThis() === null);
+ } catch (Throwable $e) {
+ $this->static = true;
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDeclaringClass(): ReflectionClass
+ {
+ return new ReflectionClass($this->className);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isPrivate(): bool
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isPublic(): bool
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isFinal(): bool
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isInternal(): bool
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isAbstract(): bool
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isStatic(): bool
+ {
+ return $this->static;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDocComment(): ?string
+ {
+ return $this->reflectionFunction->getDocComment() ?: null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFileName()
+ {
+ return $this->reflectionFunction->getFileName();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName(): string
+ {
+ return $this->methodName;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getParameters(): array
+ {
+ return $this->parameters;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getReturnType(): ?ReflectionType
+ {
+ return $this->reflectionFunction->getReturnType();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getStartLine()
+ {
+ return $this->reflectionFunction->getStartLine();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getEndLine()
+ {
+ return $this->reflectionFunction->getEndLine();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isDeprecated(): TrinaryLogic
+ {
+ return TrinaryLogic::createFromBoolean(
+ $this->reflectionFunction->isDeprecated() ||
+ preg_match('/@deprecated/i', $this->getDocComment() ?: '')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isVariadic(): bool
+ {
+ return $this->reflectionFunction->isVariadic();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPrototype(): BuiltinMethodReflection
+ {
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getReflection(): ?ReflectionMethod
+ {
+ return $this->reflectionFunction instanceof ReflectionMethod
+ ? $this->reflectionFunction
+ : null;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/PHPStan/MacroExtension.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/PHPStan/MacroExtension.php
new file mode 100644
index 0000000..5a3d694
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/PHPStan/MacroExtension.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Carbon\PHPStan;
+
+use PHPStan\Reflection\ClassReflection;
+use PHPStan\Reflection\MethodReflection;
+use PHPStan\Reflection\MethodsClassReflectionExtension;
+use PHPStan\Reflection\Php\PhpMethodReflectionFactory;
+use PHPStan\Type\TypehintHelper;
+
+/**
+ * Class MacroExtension.
+ *
+ * @codeCoverageIgnore Pure PHPStan wrapper.
+ */
+final class MacroExtension implements MethodsClassReflectionExtension
+{
+ /**
+ * @var PhpMethodReflectionFactory
+ */
+ protected $methodReflectionFactory;
+
+ /**
+ * @var MacroScanner
+ */
+ protected $scanner;
+
+ /**
+ * Extension constructor.
+ *
+ * @param PhpMethodReflectionFactory $methodReflectionFactory
+ */
+ public function __construct(PhpMethodReflectionFactory $methodReflectionFactory)
+ {
+ $this->scanner = new MacroScanner();
+ $this->methodReflectionFactory = $methodReflectionFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasMethod(ClassReflection $classReflection, string $methodName): bool
+ {
+ return $this->scanner->hasMethod($classReflection->getName(), $methodName);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
+ {
+ $builtinMacro = $this->scanner->getMethod($classReflection->getName(), $methodName);
+
+ return $this->methodReflectionFactory->create(
+ $classReflection,
+ null,
+ $builtinMacro,
+ $classReflection->getActiveTemplateTypeMap(),
+ [],
+ TypehintHelper::decideTypeFromReflection($builtinMacro->getReturnType()),
+ null,
+ null,
+ $builtinMacro->isDeprecated()->yes(),
+ $builtinMacro->isInternal(),
+ $builtinMacro->isFinal(),
+ $builtinMacro->getDocComment()
+ );
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/PHPStan/MacroScanner.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/PHPStan/MacroScanner.php
new file mode 100644
index 0000000..97cf0b8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/PHPStan/MacroScanner.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Carbon\PHPStan;
+
+use Carbon\CarbonInterface;
+use ReflectionClass;
+use ReflectionException;
+
+final class MacroScanner
+{
+ /**
+ * Return true if the given pair class-method is a Carbon macro.
+ *
+ * @param string $className
+ * @phpstan-param class-string $className
+ *
+ * @param string $methodName
+ *
+ * @return bool
+ */
+ public function hasMethod(string $className, string $methodName): bool
+ {
+ return is_a($className, CarbonInterface::class, true) &&
+ \is_callable([$className, 'hasMacro']) &&
+ $className::hasMacro($methodName);
+ }
+
+ /**
+ * Return the Macro for a given pair class-method.
+ *
+ * @param string $className
+ * @phpstan-param class-string $className
+ *
+ * @param string $methodName
+ *
+ * @throws ReflectionException
+ *
+ * @return Macro
+ */
+ public function getMethod(string $className, string $methodName): Macro
+ {
+ $reflectionClass = new ReflectionClass($className);
+ $property = $reflectionClass->getProperty('globalMacros');
+
+ $property->setAccessible(true);
+ $macro = $property->getValue()[$methodName];
+
+ return new Macro(
+ $className,
+ $methodName,
+ $macro
+ );
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Boundaries.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Boundaries.php
new file mode 100644
index 0000000..7fbb1a3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Boundaries.php
@@ -0,0 +1,442 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\Exceptions\UnknownUnitException;
+
+/**
+ * Trait Boundaries.
+ *
+ * startOf, endOf and derived method for each unit.
+ *
+ * Depends on the following properties:
+ *
+ * @property int $year
+ * @property int $month
+ * @property int $daysInMonth
+ * @property int $quarter
+ *
+ * Depends on the following methods:
+ *
+ * @method $this setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0)
+ * @method $this setDate(int $year, int $month, int $day)
+ * @method $this addMonths(int $value = 1)
+ */
+trait Boundaries
+{
+ /**
+ * Resets the time to 00:00:00 start of day
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfDay();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfDay()
+ {
+ return $this->setTime(0, 0, 0, 0);
+ }
+
+ /**
+ * Resets the time to 23:59:59.999999 end of day
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfDay();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfDay()
+ {
+ return $this->setTime(static::HOURS_PER_DAY - 1, static::MINUTES_PER_HOUR - 1, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1);
+ }
+
+ /**
+ * Resets the date to the first day of the month and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfMonth();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfMonth()
+ {
+ return $this->setDate($this->year, $this->month, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the month and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfMonth();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfMonth()
+ {
+ return $this->setDate($this->year, $this->month, $this->daysInMonth)->endOfDay();
+ }
+
+ /**
+ * Resets the date to the first day of the quarter and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfQuarter();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfQuarter()
+ {
+ $month = ($this->quarter - 1) * static::MONTHS_PER_QUARTER + 1;
+
+ return $this->setDate($this->year, $month, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the quarter and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfQuarter();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfQuarter()
+ {
+ return $this->startOfQuarter()->addMonths(static::MONTHS_PER_QUARTER - 1)->endOfMonth();
+ }
+
+ /**
+ * Resets the date to the first day of the year and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfYear();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfYear()
+ {
+ return $this->setDate($this->year, 1, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the year and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfYear();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfYear()
+ {
+ return $this->setDate($this->year, 12, 31)->endOfDay();
+ }
+
+ /**
+ * Resets the date to the first day of the decade and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfDecade();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfDecade()
+ {
+ $year = $this->year - $this->year % static::YEARS_PER_DECADE;
+
+ return $this->setDate($year, 1, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the decade and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfDecade();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfDecade()
+ {
+ $year = $this->year - $this->year % static::YEARS_PER_DECADE + static::YEARS_PER_DECADE - 1;
+
+ return $this->setDate($year, 12, 31)->endOfDay();
+ }
+
+ /**
+ * Resets the date to the first day of the century and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfCentury();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfCentury()
+ {
+ $year = $this->year - ($this->year - 1) % static::YEARS_PER_CENTURY;
+
+ return $this->setDate($year, 1, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the century and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfCentury();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfCentury()
+ {
+ $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_CENTURY + static::YEARS_PER_CENTURY;
+
+ return $this->setDate($year, 12, 31)->endOfDay();
+ }
+
+ /**
+ * Resets the date to the first day of the millennium and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfMillennium();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfMillennium()
+ {
+ $year = $this->year - ($this->year - 1) % static::YEARS_PER_MILLENNIUM;
+
+ return $this->setDate($year, 1, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the millennium and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfMillennium();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfMillennium()
+ {
+ $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_MILLENNIUM + static::YEARS_PER_MILLENNIUM;
+
+ return $this->setDate($year, 12, 31)->endOfDay();
+ }
+
+ /**
+ * Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek() . "\n";
+ * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->startOfWeek() . "\n";
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek(Carbon::SUNDAY) . "\n";
+ * ```
+ *
+ * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
+ *
+ * @return static
+ */
+ public function startOfWeek($weekStartsAt = null)
+ {
+ return $this->subDays((7 + $this->dayOfWeek - ($weekStartsAt ?? $this->firstWeekDay)) % 7)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59.999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek() . "\n";
+ * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->endOfWeek() . "\n";
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek(Carbon::SATURDAY) . "\n";
+ * ```
+ *
+ * @param int $weekEndsAt optional start allow you to specify the day of week to use to end the week
+ *
+ * @return static
+ */
+ public function endOfWeek($weekEndsAt = null)
+ {
+ return $this->addDays((7 - $this->dayOfWeek + ($weekEndsAt ?? $this->lastWeekDay)) % 7)->endOfDay();
+ }
+
+ /**
+ * Modify to start of current hour, minutes and seconds become 0
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfHour();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfHour()
+ {
+ return $this->setTime($this->hour, 0, 0, 0);
+ }
+
+ /**
+ * Modify to end of current hour, minutes and seconds become 59
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfHour();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfHour()
+ {
+ return $this->setTime($this->hour, static::MINUTES_PER_HOUR - 1, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1);
+ }
+
+ /**
+ * Modify to start of current minute, seconds become 0
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->startOfMinute();
+ * ```
+ *
+ * @return static
+ */
+ public function startOfMinute()
+ {
+ return $this->setTime($this->hour, $this->minute, 0, 0);
+ }
+
+ /**
+ * Modify to end of current minute, seconds become 59
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16')->endOfMinute();
+ * ```
+ *
+ * @return static
+ */
+ public function endOfMinute()
+ {
+ return $this->setTime($this->hour, $this->minute, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1);
+ }
+
+ /**
+ * Modify to start of current second, microseconds become 0
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16.334455')
+ * ->startOfSecond()
+ * ->format('H:i:s.u');
+ * ```
+ *
+ * @return static
+ */
+ public function startOfSecond()
+ {
+ return $this->setTime($this->hour, $this->minute, $this->second, 0);
+ }
+
+ /**
+ * Modify to end of current second, microseconds become 999999
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16.334455')
+ * ->endOfSecond()
+ * ->format('H:i:s.u');
+ * ```
+ *
+ * @return static
+ */
+ public function endOfSecond()
+ {
+ return $this->setTime($this->hour, $this->minute, $this->second, static::MICROSECONDS_PER_SECOND - 1);
+ }
+
+ /**
+ * Modify to start of current given unit.
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16.334455')
+ * ->startOf('month')
+ * ->endOf('week', Carbon::FRIDAY);
+ * ```
+ *
+ * @param string $unit
+ * @param array<int, mixed> $params
+ *
+ * @return static
+ */
+ public function startOf($unit, ...$params)
+ {
+ $ucfUnit = ucfirst(static::singularUnit($unit));
+ $method = "startOf$ucfUnit";
+ if (!method_exists($this, $method)) {
+ throw new UnknownUnitException($unit);
+ }
+
+ return $this->$method(...$params);
+ }
+
+ /**
+ * Modify to end of current given unit.
+ *
+ * @example
+ * ```
+ * echo Carbon::parse('2018-07-25 12:45:16.334455')
+ * ->startOf('month')
+ * ->endOf('week', Carbon::FRIDAY);
+ * ```
+ *
+ * @param string $unit
+ * @param array<int, mixed> $params
+ *
+ * @return static
+ */
+ public function endOf($unit, ...$params)
+ {
+ $ucfUnit = ucfirst(static::singularUnit($unit));
+ $method = "endOf$ucfUnit";
+ if (!method_exists($this, $method)) {
+ throw new UnknownUnitException($unit);
+ }
+
+ return $this->$method(...$params);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Cast.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Cast.php
new file mode 100644
index 0000000..44caf0b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Cast.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Carbon\Traits;
+
+use Carbon\Exceptions\InvalidCastException;
+use DateTimeInterface;
+
+/**
+ * Trait Cast.
+ *
+ * Utils to cast into an other class.
+ */
+trait Cast
+{
+ /**
+ * Cast the current instance into the given class.
+ *
+ * @param string $className The $className::instance() method will be called to cast the current object.
+ *
+ * @return DateTimeInterface
+ */
+ public function cast(string $className)
+ {
+ if (!method_exists($className, 'instance')) {
+ if (is_a($className, DateTimeInterface::class, true)) {
+ return new $className($this->rawFormat('Y-m-d H:i:s.u'), $this->getTimezone());
+ }
+
+ throw new InvalidCastException("$className has not the instance() method needed to cast the date.");
+ }
+
+ return $className::instance($this);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Comparison.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Comparison.php
new file mode 100644
index 0000000..ee00666
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Comparison.php
@@ -0,0 +1,1069 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use BadMethodCallException;
+use Carbon\CarbonInterface;
+use Carbon\Exceptions\BadComparisonUnitException;
+use InvalidArgumentException;
+
+/**
+ * Trait Comparison.
+ *
+ * Comparison utils and testers. All the following methods return booleans.
+ * nowWithSameTz
+ *
+ * Depends on the following methods:
+ *
+ * @method static resolveCarbon($date)
+ * @method static copy()
+ * @method static nowWithSameTz()
+ * @method static static yesterday($timezone = null)
+ * @method static static tomorrow($timezone = null)
+ */
+trait Comparison
+{
+ /** @var bool */
+ protected $endOfTime = false;
+
+ /** @var bool */
+ protected $startOfTime = false;
+
+ /**
+ * Determines if the instance is equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->eq(Carbon::parse('2018-07-25 12:45:16')); // true
+ * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see equalTo()
+ *
+ * @return bool
+ */
+ public function eq($date): bool
+ {
+ return $this->equalTo($date);
+ }
+
+ /**
+ * Determines if the instance is equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->equalTo(Carbon::parse('2018-07-25 12:45:16')); // true
+ * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function equalTo($date): bool
+ {
+ return $this == $date;
+ }
+
+ /**
+ * Determines if the instance is not equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->ne(Carbon::parse('2018-07-25 12:45:16')); // false
+ * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see notEqualTo()
+ *
+ * @return bool
+ */
+ public function ne($date): bool
+ {
+ return $this->notEqualTo($date);
+ }
+
+ /**
+ * Determines if the instance is not equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->notEqualTo(Carbon::parse('2018-07-25 12:45:16')); // false
+ * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function notEqualTo($date): bool
+ {
+ return !$this->equalTo($date);
+ }
+
+ /**
+ * Determines if the instance is greater (after) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:15'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see greaterThan()
+ *
+ * @return bool
+ */
+ public function gt($date): bool
+ {
+ return $this->greaterThan($date);
+ }
+
+ /**
+ * Determines if the instance is greater (after) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:15'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function greaterThan($date): bool
+ {
+ return $this > $date;
+ }
+
+ /**
+ * Determines if the instance is greater (after) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:15'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see greaterThan()
+ *
+ * @return bool
+ */
+ public function isAfter($date): bool
+ {
+ return $this->greaterThan($date);
+ }
+
+ /**
+ * Determines if the instance is greater (after) than or equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:15'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see greaterThanOrEqualTo()
+ *
+ * @return bool
+ */
+ public function gte($date): bool
+ {
+ return $this->greaterThanOrEqualTo($date);
+ }
+
+ /**
+ * Determines if the instance is greater (after) than or equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:15'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:17'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function greaterThanOrEqualTo($date): bool
+ {
+ return $this >= $date;
+ }
+
+ /**
+ * Determines if the instance is less (before) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:15'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see lessThan()
+ *
+ * @return bool
+ */
+ public function lt($date): bool
+ {
+ return $this->lessThan($date);
+ }
+
+ /**
+ * Determines if the instance is less (before) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:15'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function lessThan($date): bool
+ {
+ return $this < $date;
+ }
+
+ /**
+ * Determines if the instance is less (before) than another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:15'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:16'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see lessThan()
+ *
+ * @return bool
+ */
+ public function isBefore($date): bool
+ {
+ return $this->lessThan($date);
+ }
+
+ /**
+ * Determines if the instance is less (before) or equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:15'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see lessThanOrEqualTo()
+ *
+ * @return bool
+ */
+ public function lte($date): bool
+ {
+ return $this->lessThanOrEqualTo($date);
+ }
+
+ /**
+ * Determines if the instance is less (before) or equal to another
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:15'); // false
+ * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:16'); // true
+ * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:17'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function lessThanOrEqualTo($date): bool
+ {
+ return $this <= $date;
+ }
+
+ /**
+ * Determines if the instance is between two others.
+ *
+ * The third argument allow you to specify if bounds are included or not (true by default)
+ * but for when you including/excluding bounds may produce different results in your application,
+ * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25')->between('2018-07-14', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->between('2018-08-01', '2018-08-20'); // false
+ * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01', false); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ * @param bool $equal Indicates if an equal to comparison should be done
+ *
+ * @return bool
+ */
+ public function between($date1, $date2, $equal = true): bool
+ {
+ $date1 = $this->resolveCarbon($date1);
+ $date2 = $this->resolveCarbon($date2);
+
+ if ($date1->greaterThan($date2)) {
+ [$date1, $date2] = [$date2, $date1];
+ }
+
+ if ($equal) {
+ return $this->greaterThanOrEqualTo($date1) && $this->lessThanOrEqualTo($date2);
+ }
+
+ return $this->greaterThan($date1) && $this->lessThan($date2);
+ }
+
+ /**
+ * Determines if the instance is between two others, bounds included.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-14', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->betweenIncluded('2018-08-01', '2018-08-20'); // false
+ * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-25', '2018-08-01'); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ *
+ * @return bool
+ */
+ public function betweenIncluded($date1, $date2): bool
+ {
+ return $this->between($date1, $date2, true);
+ }
+
+ /**
+ * Determines if the instance is between two others, bounds excluded.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-14', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->betweenExcluded('2018-08-01', '2018-08-20'); // false
+ * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-25', '2018-08-01'); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ *
+ * @return bool
+ */
+ public function betweenExcluded($date1, $date2): bool
+ {
+ return $this->between($date1, $date2, false);
+ }
+
+ /**
+ * Determines if the instance is between two others
+ *
+ * @example
+ * ```
+ * Carbon::parse('2018-07-25')->isBetween('2018-07-14', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->isBetween('2018-08-01', '2018-08-20'); // false
+ * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01'); // true
+ * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01', false); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ * @param bool $equal Indicates if an equal to comparison should be done
+ *
+ * @return bool
+ */
+ public function isBetween($date1, $date2, $equal = true): bool
+ {
+ return $this->between($date1, $date2, $equal);
+ }
+
+ /**
+ * Determines if the instance is a weekday.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-07-14')->isWeekday(); // false
+ * Carbon::parse('2019-07-15')->isWeekday(); // true
+ * ```
+ *
+ * @return bool
+ */
+ public function isWeekday()
+ {
+ return !$this->isWeekend();
+ }
+
+ /**
+ * Determines if the instance is a weekend day.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-07-14')->isWeekend(); // true
+ * Carbon::parse('2019-07-15')->isWeekend(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isWeekend()
+ {
+ return \in_array($this->dayOfWeek, static::$weekendDays);
+ }
+
+ /**
+ * Determines if the instance is yesterday.
+ *
+ * @example
+ * ```
+ * Carbon::yesterday()->isYesterday(); // true
+ * Carbon::tomorrow()->isYesterday(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isYesterday()
+ {
+ return $this->toDateString() === static::yesterday($this->getTimezone())->toDateString();
+ }
+
+ /**
+ * Determines if the instance is today.
+ *
+ * @example
+ * ```
+ * Carbon::today()->isToday(); // true
+ * Carbon::tomorrow()->isToday(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isToday()
+ {
+ return $this->toDateString() === $this->nowWithSameTz()->toDateString();
+ }
+
+ /**
+ * Determines if the instance is tomorrow.
+ *
+ * @example
+ * ```
+ * Carbon::tomorrow()->isTomorrow(); // true
+ * Carbon::yesterday()->isTomorrow(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isTomorrow()
+ {
+ return $this->toDateString() === static::tomorrow($this->getTimezone())->toDateString();
+ }
+
+ /**
+ * Determines if the instance is in the future, ie. greater (after) than now.
+ *
+ * @example
+ * ```
+ * Carbon::now()->addHours(5)->isFuture(); // true
+ * Carbon::now()->subHours(5)->isFuture(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isFuture()
+ {
+ return $this->greaterThan($this->nowWithSameTz());
+ }
+
+ /**
+ * Determines if the instance is in the past, ie. less (before) than now.
+ *
+ * @example
+ * ```
+ * Carbon::now()->subHours(5)->isPast(); // true
+ * Carbon::now()->addHours(5)->isPast(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isPast()
+ {
+ return $this->lessThan($this->nowWithSameTz());
+ }
+
+ /**
+ * Determines if the instance is a leap year.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2020-01-01')->isLeapYear(); // true
+ * Carbon::parse('2019-01-01')->isLeapYear(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isLeapYear()
+ {
+ return $this->rawFormat('L') === '1';
+ }
+
+ /**
+ * Determines if the instance is a long year
+ *
+ * @example
+ * ```
+ * Carbon::parse('2015-01-01')->isLongYear(); // true
+ * Carbon::parse('2016-01-01')->isLongYear(); // false
+ * ```
+ *
+ * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
+ *
+ * @return bool
+ */
+ public function isLongYear()
+ {
+ return static::create($this->year, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === 53;
+ }
+
+ /**
+ * Compares the formatted values of the two dates.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-12-13')); // true
+ * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-06-14')); // false
+ * ```
+ *
+ * @param string $format date formats to compare.
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date instance to compare with or null to use current day.
+ *
+ * @return bool
+ */
+ public function isSameAs($format, $date = null)
+ {
+ return $this->rawFormat($format) === $this->resolveCarbon($date)->rawFormat($format);
+ }
+
+ /**
+ * Determines if the instance is in the current unit given.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-01-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // true
+ * Carbon::parse('2018-12-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // false
+ * ```
+ *
+ * @param string $unit singular unit string
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date instance to compare with or null to use current day.
+ *
+ * @throws BadComparisonUnitException
+ *
+ * @return bool
+ */
+ public function isSameUnit($unit, $date = null)
+ {
+ $units = [
+ // @call isSameUnit
+ 'year' => 'Y',
+ // @call isSameUnit
+ 'week' => 'o-W',
+ // @call isSameUnit
+ 'day' => 'Y-m-d',
+ // @call isSameUnit
+ 'hour' => 'Y-m-d H',
+ // @call isSameUnit
+ 'minute' => 'Y-m-d H:i',
+ // @call isSameUnit
+ 'second' => 'Y-m-d H:i:s',
+ // @call isSameUnit
+ 'micro' => 'Y-m-d H:i:s.u',
+ // @call isSameUnit
+ 'microsecond' => 'Y-m-d H:i:s.u',
+ ];
+
+ if (!isset($units[$unit])) {
+ if (isset($this->$unit)) {
+ return $this->resolveCarbon($date)->$unit === $this->$unit;
+ }
+
+ if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
+ throw new BadComparisonUnitException($unit);
+ }
+
+ return false;
+ }
+
+ return $this->isSameAs($units[$unit], $date);
+ }
+
+ /**
+ * Determines if the instance is in the current unit given.
+ *
+ * @example
+ * ```
+ * Carbon::now()->isCurrentUnit('hour'); // true
+ * Carbon::now()->subHours(2)->isCurrentUnit('hour'); // false
+ * ```
+ *
+ * @param string $unit The unit to test.
+ *
+ * @throws BadMethodCallException
+ *
+ * @return bool
+ */
+ public function isCurrentUnit($unit)
+ {
+ return $this->{'isSame'.ucfirst($unit)}();
+ }
+
+ /**
+ * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed).
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-03-01')); // true
+ * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-04-01')); // false
+ * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01')); // false
+ * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01'), false); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date The instance to compare with or null to use current day.
+ * @param bool $ofSameYear Check if it is the same month in the same year.
+ *
+ * @return bool
+ */
+ public function isSameQuarter($date = null, $ofSameYear = true)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return $this->quarter === $date->quarter && (!$ofSameYear || $this->isSameYear($date));
+ }
+
+ /**
+ * Checks if the passed in date is in the same month as the instance´s month.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-01-01')); // true
+ * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-02-01')); // false
+ * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01')); // false
+ * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01'), false); // true
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ * @param bool $ofSameYear Check if it is the same month in the same year.
+ *
+ * @return bool
+ */
+ public function isSameMonth($date = null, $ofSameYear = true)
+ {
+ return $this->isSameAs($ofSameYear ? 'Y-m' : 'm', $date);
+ }
+
+ /**
+ * Checks if this day is a specific day of the week.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::WEDNESDAY); // true
+ * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::FRIDAY); // false
+ * Carbon::parse('2019-07-17')->isDayOfWeek('Wednesday'); // true
+ * Carbon::parse('2019-07-17')->isDayOfWeek('Friday'); // false
+ * ```
+ *
+ * @param int $dayOfWeek
+ *
+ * @return bool
+ */
+ public function isDayOfWeek($dayOfWeek)
+ {
+ if (\is_string($dayOfWeek) && \defined($constant = static::class.'::'.strtoupper($dayOfWeek))) {
+ $dayOfWeek = \constant($constant);
+ }
+
+ return $this->dayOfWeek === $dayOfWeek;
+ }
+
+ /**
+ * Check if its the birthday. Compares the date/month values of the two dates.
+ *
+ * @example
+ * ```
+ * Carbon::now()->subYears(5)->isBirthday(); // true
+ * Carbon::now()->subYears(5)->subDay()->isBirthday(); // false
+ * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-05')); // true
+ * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-06')); // false
+ * ```
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
+ *
+ * @return bool
+ */
+ public function isBirthday($date = null)
+ {
+ return $this->isSameAs('md', $date);
+ }
+
+ /**
+ * Check if today is the last day of the Month
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-02-28')->isLastOfMonth(); // true
+ * Carbon::parse('2019-03-28')->isLastOfMonth(); // false
+ * Carbon::parse('2019-03-30')->isLastOfMonth(); // false
+ * Carbon::parse('2019-03-31')->isLastOfMonth(); // true
+ * Carbon::parse('2019-04-30')->isLastOfMonth(); // true
+ * ```
+ *
+ * @return bool
+ */
+ public function isLastOfMonth()
+ {
+ return $this->day === $this->daysInMonth;
+ }
+
+ /**
+ * Check if the instance is start of day / midnight.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-02-28 00:00:00')->isStartOfDay(); // true
+ * Carbon::parse('2019-02-28 00:00:00.999999')->isStartOfDay(); // true
+ * Carbon::parse('2019-02-28 00:00:01')->isStartOfDay(); // false
+ * Carbon::parse('2019-02-28 00:00:00.000000')->isStartOfDay(true); // true
+ * Carbon::parse('2019-02-28 00:00:00.000012')->isStartOfDay(true); // false
+ * ```
+ *
+ * @param bool $checkMicroseconds check time at microseconds precision
+ *
+ * @return bool
+ */
+ public function isStartOfDay($checkMicroseconds = false)
+ {
+ /* @var CarbonInterface $this */
+ return $checkMicroseconds
+ ? $this->rawFormat('H:i:s.u') === '00:00:00.000000'
+ : $this->rawFormat('H:i:s') === '00:00:00';
+ }
+
+ /**
+ * Check if the instance is end of day.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(); // true
+ * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(); // true
+ * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(); // true
+ * Carbon::parse('2019-02-28 23:59:58.999999')->isEndOfDay(); // false
+ * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(true); // true
+ * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(true); // false
+ * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(true); // false
+ * ```
+ *
+ * @param bool $checkMicroseconds check time at microseconds precision
+ *
+ * @return bool
+ */
+ public function isEndOfDay($checkMicroseconds = false)
+ {
+ /* @var CarbonInterface $this */
+ return $checkMicroseconds
+ ? $this->rawFormat('H:i:s.u') === '23:59:59.999999'
+ : $this->rawFormat('H:i:s') === '23:59:59';
+ }
+
+ /**
+ * Check if the instance is start of day / midnight.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-02-28 00:00:00')->isMidnight(); // true
+ * Carbon::parse('2019-02-28 00:00:00.999999')->isMidnight(); // true
+ * Carbon::parse('2019-02-28 00:00:01')->isMidnight(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isMidnight()
+ {
+ return $this->isStartOfDay();
+ }
+
+ /**
+ * Check if the instance is midday.
+ *
+ * @example
+ * ```
+ * Carbon::parse('2019-02-28 11:59:59.999999')->isMidday(); // false
+ * Carbon::parse('2019-02-28 12:00:00')->isMidday(); // true
+ * Carbon::parse('2019-02-28 12:00:00.999999')->isMidday(); // true
+ * Carbon::parse('2019-02-28 12:00:01')->isMidday(); // false
+ * ```
+ *
+ * @return bool
+ */
+ public function isMidday()
+ {
+ /* @var CarbonInterface $this */
+ return $this->rawFormat('G:i:s') === static::$midDayAt.':00:00';
+ }
+
+ /**
+ * Checks if the (date)time string is in a given format.
+ *
+ * @example
+ * ```
+ * Carbon::hasFormat('11:12:45', 'h:i:s'); // true
+ * Carbon::hasFormat('13:12:45', 'h:i:s'); // false
+ * ```
+ *
+ * @param string $date
+ * @param string $format
+ *
+ * @return bool
+ */
+ public static function hasFormat($date, $format)
+ {
+ // createFromFormat() is known to handle edge cases silently.
+ // E.g. "1975-5-1" (Y-n-j) will still be parsed correctly when "Y-m-d" is supplied as the format.
+ // To ensure we're really testing against our desired format, perform an additional regex validation.
+
+ return self::matchFormatPattern((string) $date, preg_quote((string) $format, '/'), static::$regexFormats);
+ }
+
+ /**
+ * Checks if the (date)time string is in a given format.
+ *
+ * @example
+ * ```
+ * Carbon::hasFormatWithModifiers('31/08/2015', 'd#m#Y'); // true
+ * Carbon::hasFormatWithModifiers('31/08/2015', 'm#d#Y'); // false
+ * ```
+ *
+ * @param string $date
+ * @param string $format
+ *
+ * @return bool
+ */
+ public static function hasFormatWithModifiers($date, $format): bool
+ {
+ return self::matchFormatPattern((string) $date, (string) $format, array_merge(static::$regexFormats, static::$regexFormatModifiers));
+ }
+
+ /**
+ * Checks if the (date)time string is in a given format and valid to create a
+ * new instance.
+ *
+ * @example
+ * ```
+ * Carbon::canBeCreatedFromFormat('11:12:45', 'h:i:s'); // true
+ * Carbon::canBeCreatedFromFormat('13:12:45', 'h:i:s'); // false
+ * ```
+ *
+ * @param string $date
+ * @param string $format
+ *
+ * @return bool
+ */
+ public static function canBeCreatedFromFormat($date, $format)
+ {
+ try {
+ // Try to create a DateTime object. Throws an InvalidArgumentException if the provided time string
+ // doesn't match the format in any way.
+ if (!static::rawCreateFromFormat($format, $date)) {
+ return false;
+ }
+ } catch (InvalidArgumentException $e) {
+ return false;
+ }
+
+ return static::hasFormatWithModifiers($date, $format);
+ }
+
+ /**
+ * Returns true if the current date matches the given string.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2018')); // false
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('06-02')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06-02')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('Sunday')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('June')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:45')); // true
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:00')); // false
+ * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12h')); // true
+ * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3pm')); // true
+ * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3am')); // false
+ * ```
+ *
+ * @param string $tester day name, month name, hour, date, etc. as string
+ *
+ * @return bool
+ */
+ public function is(string $tester)
+ {
+ $tester = trim($tester);
+
+ if (preg_match('/^\d+$/', $tester)) {
+ return $this->year === (int) $tester;
+ }
+
+ if (preg_match('/^\d{3,}-\d{1,2}$/', $tester)) {
+ return $this->isSameMonth(static::parse($tester));
+ }
+
+ if (preg_match('/^\d{1,2}-\d{1,2}$/', $tester)) {
+ return $this->isSameDay(static::parse($this->year.'-'.$tester));
+ }
+
+ $modifier = preg_replace('/(\d)h$/i', '$1:00', $tester);
+
+ /* @var CarbonInterface $max */
+ $median = static::parse('5555-06-15 12:30:30.555555')->modify($modifier);
+ $current = $this->avoidMutation();
+ /* @var CarbonInterface $other */
+ $other = $this->avoidMutation()->modify($modifier);
+
+ if ($current->eq($other)) {
+ return true;
+ }
+
+ if (preg_match('/\d:\d{1,2}:\d{1,2}$/', $tester)) {
+ return $current->startOfSecond()->eq($other);
+ }
+
+ if (preg_match('/\d:\d{1,2}$/', $tester)) {
+ return $current->startOfMinute()->eq($other);
+ }
+
+ if (preg_match('/\d(h|am|pm)$/', $tester)) {
+ return $current->startOfHour()->eq($other);
+ }
+
+ if (preg_match(
+ '/^(january|february|march|april|may|june|july|august|september|october|november|december)\s+\d+$/i',
+ $tester
+ )) {
+ return $current->startOfMonth()->eq($other->startOfMonth());
+ }
+
+ $units = [
+ 'month' => [1, 'year'],
+ 'day' => [1, 'month'],
+ 'hour' => [0, 'day'],
+ 'minute' => [0, 'hour'],
+ 'second' => [0, 'minute'],
+ 'microsecond' => [0, 'second'],
+ ];
+
+ foreach ($units as $unit => [$minimum, $startUnit]) {
+ if ($minimum === $median->$unit) {
+ $current = $current->startOf($startUnit);
+
+ break;
+ }
+ }
+
+ return $current->eq($other);
+ }
+
+ /**
+ * Checks if the (date)time string is in a given format with
+ * given list of pattern replacements.
+ *
+ * @example
+ * ```
+ * Carbon::hasFormat('11:12:45', 'h:i:s'); // true
+ * Carbon::hasFormat('13:12:45', 'h:i:s'); // false
+ * ```
+ *
+ * @param string $date
+ * @param string $format
+ * @param array $replacements
+ *
+ * @return bool
+ */
+ private static function matchFormatPattern(string $date, string $format, array $replacements): bool
+ {
+ // Preg quote, but remove escaped backslashes since we'll deal with escaped characters in the format string.
+ $regex = str_replace('\\\\', '\\', $format);
+ // Replace not-escaped letters
+ $regex = preg_replace_callback(
+ '/(?<!\\\\)((?:\\\\{2})*)(['.implode('', array_keys($replacements)).'])/',
+ function ($match) use ($replacements) {
+ return $match[1].strtr($match[2], $replacements);
+ },
+ $regex
+ );
+ // Replace escaped letters by the letter itself
+ $regex = preg_replace('/(?<!\\\\)((?:\\\\{2})*)\\\\(\w)/', '$1$2', $regex);
+ // Escape not escaped slashes
+ $regex = preg_replace('#(?<!\\\\)((?:\\\\{2})*)/#', '$1\\/', $regex);
+
+ return (bool) @preg_match('/^'.$regex.'$/', $date);
+ }
+
+ /**
+ * Returns true if the date was created using CarbonImmutable::startOfTime()
+ *
+ * @return bool
+ */
+ public function isStartOfTime(): bool
+ {
+ return $this->startOfTime ?? false;
+ }
+
+ /**
+ * Returns true if the date was created using CarbonImmutable::endOfTime()
+ *
+ * @return bool
+ */
+ public function isEndOfTime(): bool
+ {
+ return $this->endOfTime ?? false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Converter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Converter.php
new file mode 100644
index 0000000..7ba6225
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Converter.php
@@ -0,0 +1,652 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\Carbon;
+use Carbon\CarbonImmutable;
+use Carbon\CarbonInterface;
+use Carbon\CarbonInterval;
+use Carbon\CarbonPeriod;
+use Carbon\Exceptions\UnitException;
+use Closure;
+use DateTime;
+use DateTimeImmutable;
+use ReturnTypeWillChange;
+
+/**
+ * Trait Converter.
+ *
+ * Change date into different string formats and types and
+ * handle the string cast.
+ *
+ * Depends on the following methods:
+ *
+ * @method static copy()
+ */
+trait Converter
+{
+ /**
+ * Format to use for __toString method when type juggling occurs.
+ *
+ * @var string|Closure|null
+ */
+ protected static $toStringFormat;
+
+ /**
+ * Reset the format used to the default when type juggling a Carbon instance to a string
+ *
+ * @return void
+ */
+ public static function resetToStringFormat()
+ {
+ static::setToStringFormat(null);
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather let Carbon object being casted to string with DEFAULT_TO_STRING_FORMAT, and
+ * use other method or custom format passed to format() method if you need to dump an other string
+ * format.
+ *
+ * Set the default format used when type juggling a Carbon instance to a string
+ *
+ * @param string|Closure|null $format
+ *
+ * @return void
+ */
+ public static function setToStringFormat($format)
+ {
+ static::$toStringFormat = $format;
+ }
+
+ /**
+ * Returns the formatted date string on success or FALSE on failure.
+ *
+ * @see https://php.net/manual/en/datetime.format.php
+ *
+ * @param string $format
+ *
+ * @return string
+ */
+ #[ReturnTypeWillChange]
+ public function format($format)
+ {
+ $function = $this->localFormatFunction ?: static::$formatFunction;
+
+ if (!$function) {
+ return $this->rawFormat($format);
+ }
+
+ if (\is_string($function) && method_exists($this, $function)) {
+ $function = [$this, $function];
+ }
+
+ return $function(...\func_get_args());
+ }
+
+ /**
+ * @see https://php.net/manual/en/datetime.format.php
+ *
+ * @param string $format
+ *
+ * @return string
+ */
+ public function rawFormat($format)
+ {
+ return parent::format($format);
+ }
+
+ /**
+ * Format the instance as a string using the set format
+ *
+ * @example
+ * ```
+ * echo Carbon::now(); // Carbon instances can be casted to string
+ * ```
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $format = $this->localToStringFormat ?? static::$toStringFormat;
+
+ return $format instanceof Closure
+ ? $format($this)
+ : $this->rawFormat($format ?: (
+ \defined('static::DEFAULT_TO_STRING_FORMAT')
+ ? static::DEFAULT_TO_STRING_FORMAT
+ : CarbonInterface::DEFAULT_TO_STRING_FORMAT
+ ));
+ }
+
+ /**
+ * Format the instance as date
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toDateString();
+ * ```
+ *
+ * @return string
+ */
+ public function toDateString()
+ {
+ return $this->rawFormat('Y-m-d');
+ }
+
+ /**
+ * Format the instance as a readable date
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toFormattedDateString();
+ * ```
+ *
+ * @return string
+ */
+ public function toFormattedDateString()
+ {
+ return $this->rawFormat('M j, Y');
+ }
+
+ /**
+ * Format the instance as time
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toTimeString();
+ * ```
+ *
+ * @param string $unitPrecision
+ *
+ * @return string
+ */
+ public function toTimeString($unitPrecision = 'second')
+ {
+ return $this->rawFormat(static::getTimeFormatByPrecision($unitPrecision));
+ }
+
+ /**
+ * Format the instance as date and time
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toDateTimeString();
+ * ```
+ *
+ * @param string $unitPrecision
+ *
+ * @return string
+ */
+ public function toDateTimeString($unitPrecision = 'second')
+ {
+ return $this->rawFormat('Y-m-d '.static::getTimeFormatByPrecision($unitPrecision));
+ }
+
+ /**
+ * Return a format from H:i to H:i:s.u according to given unit precision.
+ *
+ * @param string $unitPrecision "minute", "second", "millisecond" or "microsecond"
+ *
+ * @return string
+ */
+ public static function getTimeFormatByPrecision($unitPrecision)
+ {
+ switch (static::singularUnit($unitPrecision)) {
+ case 'minute':
+ return 'H:i';
+ case 'second':
+ return 'H:i:s';
+ case 'm':
+ case 'millisecond':
+ return 'H:i:s.v';
+ case 'µ':
+ case 'microsecond':
+ return 'H:i:s.u';
+ }
+
+ throw new UnitException('Precision unit expected among: minute, second, millisecond and microsecond.');
+ }
+
+ /**
+ * Format the instance as date and time T-separated with no timezone
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toDateTimeLocalString();
+ * echo "\n";
+ * echo Carbon::now()->toDateTimeLocalString('minute'); // You can specify precision among: minute, second, millisecond and microsecond
+ * ```
+ *
+ * @param string $unitPrecision
+ *
+ * @return string
+ */
+ public function toDateTimeLocalString($unitPrecision = 'second')
+ {
+ return $this->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision));
+ }
+
+ /**
+ * Format the instance with day, date and time
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toDayDateTimeString();
+ * ```
+ *
+ * @return string
+ */
+ public function toDayDateTimeString()
+ {
+ return $this->rawFormat('D, M j, Y g:i A');
+ }
+
+ /**
+ * Format the instance as ATOM
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toAtomString();
+ * ```
+ *
+ * @return string
+ */
+ public function toAtomString()
+ {
+ return $this->rawFormat(DateTime::ATOM);
+ }
+
+ /**
+ * Format the instance as COOKIE
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toCookieString();
+ * ```
+ *
+ * @return string
+ */
+ public function toCookieString()
+ {
+ return $this->rawFormat(DateTime::COOKIE);
+ }
+
+ /**
+ * Format the instance as ISO8601
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toIso8601String();
+ * ```
+ *
+ * @return string
+ */
+ public function toIso8601String()
+ {
+ return $this->toAtomString();
+ }
+
+ /**
+ * Format the instance as RFC822
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc822String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc822String()
+ {
+ return $this->rawFormat(DateTime::RFC822);
+ }
+
+ /**
+ * Convert the instance to UTC and return as Zulu ISO8601
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toIso8601ZuluString();
+ * ```
+ *
+ * @param string $unitPrecision
+ *
+ * @return string
+ */
+ public function toIso8601ZuluString($unitPrecision = 'second')
+ {
+ return $this->avoidMutation()
+ ->utc()
+ ->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision).'\Z');
+ }
+
+ /**
+ * Format the instance as RFC850
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc850String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc850String()
+ {
+ return $this->rawFormat(DateTime::RFC850);
+ }
+
+ /**
+ * Format the instance as RFC1036
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc1036String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc1036String()
+ {
+ return $this->rawFormat(DateTime::RFC1036);
+ }
+
+ /**
+ * Format the instance as RFC1123
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc1123String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc1123String()
+ {
+ return $this->rawFormat(DateTime::RFC1123);
+ }
+
+ /**
+ * Format the instance as RFC2822
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc2822String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc2822String()
+ {
+ return $this->rawFormat(DateTime::RFC2822);
+ }
+
+ /**
+ * Format the instance as RFC3339
+ *
+ * @param bool $extended
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc3339String() . "\n";
+ * echo Carbon::now()->toRfc3339String(true) . "\n";
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc3339String($extended = false)
+ {
+ $format = DateTime::RFC3339;
+ if ($extended) {
+ $format = DateTime::RFC3339_EXTENDED;
+ }
+
+ return $this->rawFormat($format);
+ }
+
+ /**
+ * Format the instance as RSS
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRssString();
+ * ```
+ *
+ * @return string
+ */
+ public function toRssString()
+ {
+ return $this->rawFormat(DateTime::RSS);
+ }
+
+ /**
+ * Format the instance as W3C
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toW3cString();
+ * ```
+ *
+ * @return string
+ */
+ public function toW3cString()
+ {
+ return $this->rawFormat(DateTime::W3C);
+ }
+
+ /**
+ * Format the instance as RFC7231
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toRfc7231String();
+ * ```
+ *
+ * @return string
+ */
+ public function toRfc7231String()
+ {
+ return $this->avoidMutation()
+ ->setTimezone('GMT')
+ ->rawFormat(\defined('static::RFC7231_FORMAT') ? static::RFC7231_FORMAT : CarbonInterface::RFC7231_FORMAT);
+ }
+
+ /**
+ * Get default array representation.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toArray());
+ * ```
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ return [
+ 'year' => $this->year,
+ 'month' => $this->month,
+ 'day' => $this->day,
+ 'dayOfWeek' => $this->dayOfWeek,
+ 'dayOfYear' => $this->dayOfYear,
+ 'hour' => $this->hour,
+ 'minute' => $this->minute,
+ 'second' => $this->second,
+ 'micro' => $this->micro,
+ 'timestamp' => $this->timestamp,
+ 'formatted' => $this->rawFormat(\defined('static::DEFAULT_TO_STRING_FORMAT') ? static::DEFAULT_TO_STRING_FORMAT : CarbonInterface::DEFAULT_TO_STRING_FORMAT),
+ 'timezone' => $this->timezone,
+ ];
+ }
+
+ /**
+ * Get default object representation.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toObject());
+ * ```
+ *
+ * @return object
+ */
+ public function toObject()
+ {
+ return (object) $this->toArray();
+ }
+
+ /**
+ * Returns english human readable complete date string.
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toString();
+ * ```
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return $this->avoidMutation()->locale('en')->isoFormat('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
+ }
+
+ /**
+ * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept:
+ * 1977-04-22T01:00:00-05:00).
+ *
+ * @example
+ * ```
+ * echo Carbon::now('America/Toronto')->toISOString() . "\n";
+ * echo Carbon::now('America/Toronto')->toISOString(true) . "\n";
+ * ```
+ *
+ * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC.
+ *
+ * @return null|string
+ */
+ public function toISOString($keepOffset = false)
+ {
+ if (!$this->isValid()) {
+ return null;
+ }
+
+ $yearFormat = $this->year < 0 || $this->year > 9999 ? 'YYYYYY' : 'YYYY';
+ $tzFormat = $keepOffset ? 'Z' : '[Z]';
+ $date = $keepOffset ? $this : $this->avoidMutation()->utc();
+
+ return $date->isoFormat("$yearFormat-MM-DD[T]HH:mm:ss.SSSSSS$tzFormat");
+ }
+
+ /**
+ * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone.
+ *
+ * @example
+ * ```
+ * echo Carbon::now('America/Toronto')->toJSON();
+ * ```
+ *
+ * @return null|string
+ */
+ public function toJSON()
+ {
+ return $this->toISOString();
+ }
+
+ /**
+ * Return native DateTime PHP object matching the current instance.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toDateTime());
+ * ```
+ *
+ * @return DateTime
+ */
+ public function toDateTime()
+ {
+ return new DateTime($this->rawFormat('Y-m-d H:i:s.u'), $this->getTimezone());
+ }
+
+ /**
+ * Return native toDateTimeImmutable PHP object matching the current instance.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toDateTimeImmutable());
+ * ```
+ *
+ * @return DateTimeImmutable
+ */
+ public function toDateTimeImmutable()
+ {
+ return new DateTimeImmutable($this->rawFormat('Y-m-d H:i:s.u'), $this->getTimezone());
+ }
+
+ /**
+ * @alias toDateTime
+ *
+ * Return native DateTime PHP object matching the current instance.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toDate());
+ * ```
+ *
+ * @return DateTime
+ */
+ public function toDate()
+ {
+ return $this->toDateTime();
+ }
+
+ /**
+ * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval).
+ *
+ * @param \DateTimeInterface|Carbon|CarbonImmutable|int|null $end period end date or recurrences count if int
+ * @param int|\DateInterval|string|null $interval period default interval or number of the given $unit
+ * @param string|null $unit if specified, $interval must be an integer
+ *
+ * @return CarbonPeriod
+ */
+ public function toPeriod($end = null, $interval = null, $unit = null)
+ {
+ if ($unit) {
+ $interval = CarbonInterval::make("$interval ".static::pluralUnit($unit));
+ }
+
+ $period = (new CarbonPeriod())->setDateClass(static::class)->setStartDate($this);
+
+ if ($interval) {
+ $period->setDateInterval($interval);
+ }
+
+ if (\is_int($end) || \is_string($end) && ctype_digit($end)) {
+ $period->setRecurrences($end);
+ } elseif ($end) {
+ $period->setEndDate($end);
+ }
+
+ return $period;
+ }
+
+ /**
+ * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval).
+ *
+ * @param \DateTimeInterface|Carbon|CarbonImmutable|null $end period end date
+ * @param int|\DateInterval|string|null $interval period default interval or number of the given $unit
+ * @param string|null $unit if specified, $interval must be an integer
+ *
+ * @return CarbonPeriod
+ */
+ public function range($end = null, $interval = null, $unit = null)
+ {
+ return $this->toPeriod($end, $interval, $unit);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Creator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Creator.php
new file mode 100644
index 0000000..fa7cfc7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Creator.php
@@ -0,0 +1,940 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\Carbon;
+use Carbon\CarbonImmutable;
+use Carbon\CarbonInterface;
+use Carbon\Exceptions\InvalidDateException;
+use Carbon\Exceptions\InvalidFormatException;
+use Carbon\Exceptions\OutOfRangeException;
+use Carbon\Translator;
+use Closure;
+use DateTimeInterface;
+use DateTimeZone;
+use Exception;
+use ReturnTypeWillChange;
+
+/**
+ * Trait Creator.
+ *
+ * Static creators.
+ *
+ * Depends on the following methods:
+ *
+ * @method static Carbon|CarbonImmutable getTestNow()
+ */
+trait Creator
+{
+ use ObjectInitialisation;
+
+ /**
+ * The errors that can occur.
+ *
+ * @var array
+ */
+ protected static $lastErrors;
+
+ /**
+ * Create a new Carbon instance.
+ *
+ * Please see the testing aids section (specifically static::setTestNow())
+ * for more on the possibility of this constructor returning a test instance.
+ *
+ * @param DateTimeInterface|string|null $time
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ */
+ public function __construct($time = null, $tz = null)
+ {
+ if ($time instanceof DateTimeInterface) {
+ $time = $this->constructTimezoneFromDateTime($time, $tz)->format('Y-m-d H:i:s.u');
+ }
+
+ if (is_numeric($time) && (!\is_string($time) || !preg_match('/^\d{1,14}$/', $time))) {
+ $time = static::createFromTimestampUTC($time)->format('Y-m-d\TH:i:s.uP');
+ }
+
+ // If the class has a test now set and we are trying to create a now()
+ // instance then override as required
+ $isNow = empty($time) || $time === 'now';
+
+ if (method_exists(static::class, 'hasTestNow') &&
+ method_exists(static::class, 'getTestNow') &&
+ static::hasTestNow() &&
+ ($isNow || static::hasRelativeKeywords($time))
+ ) {
+ static::mockConstructorParameters($time, $tz);
+ }
+
+ // Work-around for PHP bug https://bugs.php.net/bug.php?id=67127
+ if (!str_contains((string) .1, '.')) {
+ $locale = setlocale(LC_NUMERIC, '0');
+ setlocale(LC_NUMERIC, 'C');
+ }
+
+ try {
+ parent::__construct($time ?: 'now', static::safeCreateDateTimeZone($tz) ?: null);
+ } catch (Exception $exception) {
+ throw new InvalidFormatException($exception->getMessage(), 0, $exception);
+ }
+
+ $this->constructedObjectId = spl_object_hash($this);
+
+ if (isset($locale)) {
+ setlocale(LC_NUMERIC, $locale);
+ }
+
+ static::setLastErrors(parent::getLastErrors());
+ }
+
+ /**
+ * Get timezone from a datetime instance.
+ *
+ * @param DateTimeInterface $date
+ * @param DateTimeZone|string|null $tz
+ *
+ * @return DateTimeInterface
+ */
+ private function constructTimezoneFromDateTime(DateTimeInterface $date, &$tz)
+ {
+ if ($tz !== null) {
+ $safeTz = static::safeCreateDateTimeZone($tz);
+
+ if ($safeTz) {
+ return $date->setTimezone($safeTz);
+ }
+
+ return $date;
+ }
+
+ $tz = $date->getTimezone();
+
+ return $date;
+ }
+
+ /**
+ * Update constructedObjectId on cloned.
+ */
+ public function __clone()
+ {
+ $this->constructedObjectId = spl_object_hash($this);
+ }
+
+ /**
+ * Create a Carbon instance from a DateTime one.
+ *
+ * @param DateTimeInterface $date
+ *
+ * @return static
+ */
+ public static function instance($date)
+ {
+ if ($date instanceof static) {
+ return clone $date;
+ }
+
+ static::expectDateTime($date);
+
+ $instance = new static($date->format('Y-m-d H:i:s.u'), $date->getTimezone());
+
+ if ($date instanceof CarbonInterface || $date instanceof Options) {
+ $settings = $date->getSettings();
+
+ if (!$date->hasLocalTranslator()) {
+ unset($settings['locale']);
+ }
+
+ $instance->settings($settings);
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Create a carbon instance from a string.
+ *
+ * This is an alias for the constructor that allows better fluent syntax
+ * as it allows you to do Carbon::parse('Monday next week')->fn() rather
+ * than (new Carbon('Monday next week'))->fn().
+ *
+ * @param string|DateTimeInterface|null $time
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function rawParse($time = null, $tz = null)
+ {
+ if ($time instanceof DateTimeInterface) {
+ return static::instance($time);
+ }
+
+ try {
+ return new static($time, $tz);
+ } catch (Exception $exception) {
+ $date = @static::now($tz)->change($time);
+
+ if (!$date) {
+ throw new InvalidFormatException("Could not parse '$time': ".$exception->getMessage(), 0, $exception);
+ }
+
+ return $date;
+ }
+ }
+
+ /**
+ * Create a carbon instance from a string.
+ *
+ * This is an alias for the constructor that allows better fluent syntax
+ * as it allows you to do Carbon::parse('Monday next week')->fn() rather
+ * than (new Carbon('Monday next week'))->fn().
+ *
+ * @param string|DateTimeInterface|null $time
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function parse($time = null, $tz = null)
+ {
+ $function = static::$parseFunction;
+
+ if (!$function) {
+ return static::rawParse($time, $tz);
+ }
+
+ if (\is_string($function) && method_exists(static::class, $function)) {
+ $function = [static::class, $function];
+ }
+
+ return $function(...\func_get_args());
+ }
+
+ /**
+ * Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
+ *
+ * @param string $time date/time string in the given language (may also contain English).
+ * @param string|null $locale if locale is null or not specified, current global locale will be
+ * used instead.
+ * @param DateTimeZone|string|null $tz optional timezone for the new instance.
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function parseFromLocale($time, $locale = null, $tz = null)
+ {
+ return static::rawParse(static::translateTimeString($time, $locale, 'en'), $tz);
+ }
+
+ /**
+ * Get a Carbon instance for the current date and time.
+ *
+ * @param DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function now($tz = null)
+ {
+ return new static(null, $tz);
+ }
+
+ /**
+ * Create a Carbon instance for today.
+ *
+ * @param DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function today($tz = null)
+ {
+ return static::rawParse('today', $tz);
+ }
+
+ /**
+ * Create a Carbon instance for tomorrow.
+ *
+ * @param DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function tomorrow($tz = null)
+ {
+ return static::rawParse('tomorrow', $tz);
+ }
+
+ /**
+ * Create a Carbon instance for yesterday.
+ *
+ * @param DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function yesterday($tz = null)
+ {
+ return static::rawParse('yesterday', $tz);
+ }
+
+ /**
+ * Create a Carbon instance for the greatest supported date.
+ *
+ * @return static
+ */
+ public static function maxValue()
+ {
+ if (self::$PHPIntSize === 4) {
+ // 32 bit
+ return static::createFromTimestamp(PHP_INT_MAX); // @codeCoverageIgnore
+ }
+
+ // 64 bit
+ return static::create(9999, 12, 31, 23, 59, 59);
+ }
+
+ /**
+ * Create a Carbon instance for the lowest supported date.
+ *
+ * @return static
+ */
+ public static function minValue()
+ {
+ if (self::$PHPIntSize === 4) {
+ // 32 bit
+ return static::createFromTimestamp(~PHP_INT_MAX); // @codeCoverageIgnore
+ }
+
+ // 64 bit
+ return static::create(1, 1, 1, 0, 0, 0);
+ }
+
+ private static function assertBetween($unit, $value, $min, $max)
+ {
+ if (static::isStrictModeEnabled() && ($value < $min || $value > $max)) {
+ throw new OutOfRangeException($unit, $min, $max, $value);
+ }
+ }
+
+ private static function createNowInstance($tz)
+ {
+ if (!static::hasTestNow()) {
+ return static::now($tz);
+ }
+
+ $now = static::getTestNow();
+
+ if ($now instanceof Closure) {
+ return $now(static::now($tz));
+ }
+
+ return $now;
+ }
+
+ /**
+ * Create a new Carbon instance from a specific date and time.
+ *
+ * If any of $year, $month or $day are set to null their now() values will
+ * be used.
+ *
+ * If $hour is null it will be set to its now() value and the default
+ * values for $minute and $second will be their now() values.
+ *
+ * If $hour is not null then the default values for $minute and $second
+ * will be 0.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ public static function create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null)
+ {
+ if (\is_string($year) && !is_numeric($year)) {
+ return static::parse($year, $tz ?: (\is_string($month) || $month instanceof DateTimeZone ? $month : null));
+ }
+
+ $defaults = null;
+ $getDefault = function ($unit) use ($tz, &$defaults) {
+ if ($defaults === null) {
+ $now = self::createNowInstance($tz);
+
+ $defaults = array_combine([
+ 'year',
+ 'month',
+ 'day',
+ 'hour',
+ 'minute',
+ 'second',
+ ], explode('-', $now->rawFormat('Y-n-j-G-i-s.u')));
+ }
+
+ return $defaults[$unit];
+ };
+
+ $year = $year === null ? $getDefault('year') : $year;
+ $month = $month === null ? $getDefault('month') : $month;
+ $day = $day === null ? $getDefault('day') : $day;
+ $hour = $hour === null ? $getDefault('hour') : $hour;
+ $minute = $minute === null ? $getDefault('minute') : $minute;
+ $second = (float) ($second === null ? $getDefault('second') : $second);
+
+ self::assertBetween('month', $month, 0, 99);
+ self::assertBetween('day', $day, 0, 99);
+ self::assertBetween('hour', $hour, 0, 99);
+ self::assertBetween('minute', $minute, 0, 99);
+ self::assertBetween('second', $second, 0, 99);
+
+ $fixYear = null;
+
+ if ($year < 0) {
+ $fixYear = $year;
+ $year = 0;
+ } elseif ($year > 9999) {
+ $fixYear = $year - 9999;
+ $year = 9999;
+ }
+
+ $second = ($second < 10 ? '0' : '').number_format($second, 6);
+ $instance = static::rawCreateFromFormat('!Y-n-j G:i:s.u', sprintf('%s-%s-%s %s:%02s:%02s', $year, $month, $day, $hour, $minute, $second), $tz);
+
+ if ($fixYear !== null) {
+ $instance = $instance->addYears($fixYear);
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Create a new safe Carbon instance from a specific date and time.
+ *
+ * If any of $year, $month or $day are set to null their now() values will
+ * be used.
+ *
+ * If $hour is null it will be set to its now() value and the default
+ * values for $minute and $second will be their now() values.
+ *
+ * If $hour is not null then the default values for $minute and $second
+ * will be 0.
+ *
+ * If one of the set values is not valid, an InvalidDateException
+ * will be thrown.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidDateException
+ *
+ * @return static|false
+ */
+ public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
+ {
+ $fields = static::getRangesByUnit();
+
+ foreach ($fields as $field => $range) {
+ if ($$field !== null && (!\is_int($$field) || $$field < $range[0] || $$field > $range[1])) {
+ if (static::isStrictModeEnabled()) {
+ throw new InvalidDateException($field, $$field);
+ }
+
+ return false;
+ }
+ }
+
+ $instance = static::create($year, $month, $day, $hour, $minute, $second, $tz);
+
+ foreach (array_reverse($fields) as $field => $range) {
+ if ($$field !== null && (!\is_int($$field) || $$field !== $instance->$field)) {
+ if (static::isStrictModeEnabled()) {
+ throw new InvalidDateException($field, $$field);
+ }
+
+ return false;
+ }
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Create a new Carbon instance from a specific date and time using strict validation.
+ *
+ * @see create()
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null): self
+ {
+ $initialStrictMode = static::isStrictModeEnabled();
+ static::useStrictMode(true);
+
+ try {
+ $date = static::create($year, $month, $day, $hour, $minute, $second, $tz);
+ } finally {
+ static::useStrictMode($initialStrictMode);
+ }
+
+ return $date;
+ }
+
+ /**
+ * Create a Carbon instance from just a date. The time portion is set to now.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function createFromDate($year = null, $month = null, $day = null, $tz = null)
+ {
+ return static::create($year, $month, $day, null, null, null, $tz);
+ }
+
+ /**
+ * Create a Carbon instance from just a date. The time portion is set to midnight.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function createMidnightDate($year = null, $month = null, $day = null, $tz = null)
+ {
+ return static::create($year, $month, $day, 0, 0, 0, $tz);
+ }
+
+ /**
+ * Create a Carbon instance from just a time. The date portion is set to today.
+ *
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null)
+ {
+ return static::create(null, null, null, $hour, $minute, $second, $tz);
+ }
+
+ /**
+ * Create a Carbon instance from a time string. The date portion is set to today.
+ *
+ * @param string $time
+ * @param DateTimeZone|string|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function createFromTimeString($time, $tz = null)
+ {
+ return static::today($tz)->setTimeFromTimeString($time);
+ }
+
+ /**
+ * @param string $format Datetime format
+ * @param string $time
+ * @param DateTimeZone|string|false|null $originalTz
+ *
+ * @return DateTimeInterface|false
+ */
+ private static function createFromFormatAndTimezone($format, $time, $originalTz)
+ {
+ // Work-around for https://bugs.php.net/bug.php?id=75577
+ // @codeCoverageIgnoreStart
+ if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) {
+ $format = str_replace('.v', '.u', $format);
+ }
+ // @codeCoverageIgnoreEnd
+
+ if ($originalTz === null) {
+ return parent::createFromFormat($format, (string) $time);
+ }
+
+ $tz = \is_int($originalTz)
+ ? @timezone_name_from_abbr('', (int) ($originalTz * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE), 1)
+ : $originalTz;
+
+ $tz = static::safeCreateDateTimeZone($tz, $originalTz);
+
+ if ($tz === false) {
+ return false;
+ }
+
+ return parent::createFromFormat($format, (string) $time, $tz);
+ }
+
+ /**
+ * Create a Carbon instance from a specific format.
+ *
+ * @param string $format Datetime format
+ * @param string $time
+ * @param DateTimeZone|string|false|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ public static function rawCreateFromFormat($format, $time, $tz = null)
+ {
+ // Work-around for https://bugs.php.net/bug.php?id=80141
+ $format = preg_replace('/(?<!\\\\)((?:\\\\{2})*)c/', '$1Y-m-d\TH:i:sP', $format);
+
+ if (preg_match('/(?<!\\\\)(?:\\\\{2})*(a|A)/', $format, $aMatches, PREG_OFFSET_CAPTURE) &&
+ preg_match('/(?<!\\\\)(?:\\\\{2})*(h|g|H|G)/', $format, $hMatches, PREG_OFFSET_CAPTURE) &&
+ $aMatches[1][1] < $hMatches[1][1] &&
+ preg_match('/(am|pm|AM|PM)/', $time)
+ ) {
+ $format = preg_replace('/^(.*)(?<!\\\\)((?:\\\\{2})*)(a|A)(.*)$/U', '$1$2$4 $3', $format);
+ $time = preg_replace('/^(.*)(am|pm|AM|PM)(.*)$/U', '$1$3 $2', $time);
+ }
+
+ // First attempt to create an instance, so that error messages are based on the unmodified format.
+ $date = self::createFromFormatAndTimezone($format, $time, $tz);
+ $lastErrors = parent::getLastErrors();
+ /** @var \Carbon\CarbonImmutable|\Carbon\Carbon|null $mock */
+ $mock = static::getMockedTestNow($tz);
+
+ if ($mock && $date instanceof DateTimeInterface) {
+ // Set timezone from mock if custom timezone was neither given directly nor as a part of format.
+ // First let's skip the part that will be ignored by the parser.
+ $nonEscaped = '(?<!\\\\)(\\\\{2})*';
+
+ $nonIgnored = preg_replace("/^.*{$nonEscaped}!/s", '', $format);
+
+ if ($tz === null && !preg_match("/{$nonEscaped}[eOPT]/", $nonIgnored)) {
+ $tz = clone $mock->getTimezone();
+ }
+
+ // Set microseconds to zero to match behavior of DateTime::createFromFormat()
+ // See https://bugs.php.net/bug.php?id=74332
+ $mock = $mock->copy()->microsecond(0);
+
+ // Prepend mock datetime only if the format does not contain non escaped unix epoch reset flag.
+ if (!preg_match("/{$nonEscaped}[!|]/", $format)) {
+ $format = static::MOCK_DATETIME_FORMAT.' '.$format;
+ $time = ($mock instanceof self ? $mock->rawFormat(static::MOCK_DATETIME_FORMAT) : $mock->format(static::MOCK_DATETIME_FORMAT)).' '.$time;
+ }
+
+ // Regenerate date from the modified format to base result on the mocked instance instead of now.
+ $date = self::createFromFormatAndTimezone($format, $time, $tz);
+ }
+
+ if ($date instanceof DateTimeInterface) {
+ $instance = static::instance($date);
+ $instance::setLastErrors($lastErrors);
+
+ return $instance;
+ }
+
+ if (static::isStrictModeEnabled()) {
+ throw new InvalidFormatException(implode(PHP_EOL, $lastErrors['errors']));
+ }
+
+ return false;
+ }
+
+ /**
+ * Create a Carbon instance from a specific format.
+ *
+ * @param string $format Datetime format
+ * @param string $time
+ * @param DateTimeZone|string|false|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ #[ReturnTypeWillChange]
+ public static function createFromFormat($format, $time, $tz = null)
+ {
+ $function = static::$createFromFormatFunction;
+
+ if (!$function) {
+ return static::rawCreateFromFormat($format, $time, $tz);
+ }
+
+ if (\is_string($function) && method_exists(static::class, $function)) {
+ $function = [static::class, $function];
+ }
+
+ return $function(...\func_get_args());
+ }
+
+ /**
+ * Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
+ *
+ * @param string $format Datetime format
+ * @param string $time
+ * @param DateTimeZone|string|false|null $tz optional timezone
+ * @param string|null $locale locale to be used for LTS, LT, LL, LLL, etc. macro-formats (en by fault, unneeded if no such macro-format in use)
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator optional custom translator to use for macro-formats
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ public static function createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null)
+ {
+ $format = preg_replace_callback('/(?<!\\\\)(\\\\{2})*(LTS|LT|[Ll]{1,4})/', function ($match) use ($locale, $translator) {
+ [$code] = $match;
+
+ static $formats = null;
+
+ if ($formats === null) {
+ $translator = $translator ?: Translator::get($locale);
+
+ $formats = [
+ 'LT' => static::getTranslationMessageWith($translator, 'formats.LT', $locale, 'h:mm A'),
+ 'LTS' => static::getTranslationMessageWith($translator, 'formats.LTS', $locale, 'h:mm:ss A'),
+ 'L' => static::getTranslationMessageWith($translator, 'formats.L', $locale, 'MM/DD/YYYY'),
+ 'LL' => static::getTranslationMessageWith($translator, 'formats.LL', $locale, 'MMMM D, YYYY'),
+ 'LLL' => static::getTranslationMessageWith($translator, 'formats.LLL', $locale, 'MMMM D, YYYY h:mm A'),
+ 'LLLL' => static::getTranslationMessageWith($translator, 'formats.LLLL', $locale, 'dddd, MMMM D, YYYY h:mm A'),
+ ];
+ }
+
+ return $formats[$code] ?? preg_replace_callback(
+ '/MMMM|MM|DD|dddd/',
+ function ($code) {
+ return mb_substr($code[0], 1);
+ },
+ $formats[strtoupper($code)] ?? ''
+ );
+ }, $format);
+
+ $format = preg_replace_callback('/(?<!\\\\)(\\\\{2})*('.CarbonInterface::ISO_FORMAT_REGEXP.'|[A-Za-z])/', function ($match) {
+ [$code] = $match;
+
+ static $replacements = null;
+
+ if ($replacements === null) {
+ $replacements = [
+ 'OD' => 'd',
+ 'OM' => 'M',
+ 'OY' => 'Y',
+ 'OH' => 'G',
+ 'Oh' => 'g',
+ 'Om' => 'i',
+ 'Os' => 's',
+ 'D' => 'd',
+ 'DD' => 'd',
+ 'Do' => 'd',
+ 'd' => '!',
+ 'dd' => '!',
+ 'ddd' => 'D',
+ 'dddd' => 'D',
+ 'DDD' => 'z',
+ 'DDDD' => 'z',
+ 'DDDo' => 'z',
+ 'e' => '!',
+ 'E' => '!',
+ 'H' => 'G',
+ 'HH' => 'H',
+ 'h' => 'g',
+ 'hh' => 'h',
+ 'k' => 'G',
+ 'kk' => 'G',
+ 'hmm' => 'gi',
+ 'hmmss' => 'gis',
+ 'Hmm' => 'Gi',
+ 'Hmmss' => 'Gis',
+ 'm' => 'i',
+ 'mm' => 'i',
+ 'a' => 'a',
+ 'A' => 'a',
+ 's' => 's',
+ 'ss' => 's',
+ 'S' => '*',
+ 'SS' => '*',
+ 'SSS' => '*',
+ 'SSSS' => '*',
+ 'SSSSS' => '*',
+ 'SSSSSS' => 'u',
+ 'SSSSSSS' => 'u*',
+ 'SSSSSSSS' => 'u*',
+ 'SSSSSSSSS' => 'u*',
+ 'M' => 'm',
+ 'MM' => 'm',
+ 'MMM' => 'M',
+ 'MMMM' => 'M',
+ 'Mo' => 'm',
+ 'Q' => '!',
+ 'Qo' => '!',
+ 'G' => '!',
+ 'GG' => '!',
+ 'GGG' => '!',
+ 'GGGG' => '!',
+ 'GGGGG' => '!',
+ 'g' => '!',
+ 'gg' => '!',
+ 'ggg' => '!',
+ 'gggg' => '!',
+ 'ggggg' => '!',
+ 'W' => '!',
+ 'WW' => '!',
+ 'Wo' => '!',
+ 'w' => '!',
+ 'ww' => '!',
+ 'wo' => '!',
+ 'x' => 'U???',
+ 'X' => 'U',
+ 'Y' => 'Y',
+ 'YY' => 'y',
+ 'YYYY' => 'Y',
+ 'YYYYY' => 'Y',
+ 'YYYYYY' => 'Y',
+ 'z' => 'e',
+ 'zz' => 'e',
+ 'Z' => 'e',
+ 'ZZ' => 'e',
+ ];
+ }
+
+ $format = $replacements[$code] ?? '?';
+
+ if ($format === '!') {
+ throw new InvalidFormatException("Format $code not supported for creation.");
+ }
+
+ return $format;
+ }, $format);
+
+ return static::rawCreateFromFormat($format, $time, $tz);
+ }
+
+ /**
+ * Create a Carbon instance from a specific format and a string in a given language.
+ *
+ * @param string $format Datetime format
+ * @param string $locale
+ * @param string $time
+ * @param DateTimeZone|string|false|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ public static function createFromLocaleFormat($format, $locale, $time, $tz = null)
+ {
+ return static::rawCreateFromFormat($format, static::translateTimeString($time, $locale, 'en'), $tz);
+ }
+
+ /**
+ * Create a Carbon instance from a specific ISO format and a string in a given language.
+ *
+ * @param string $format Datetime ISO format
+ * @param string $locale
+ * @param string $time
+ * @param DateTimeZone|string|false|null $tz
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|false
+ */
+ public static function createFromLocaleIsoFormat($format, $locale, $time, $tz = null)
+ {
+ $time = static::translateTimeString($time, $locale, 'en', CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS | CarbonInterface::TRANSLATE_MERIDIEM);
+
+ return static::createFromIsoFormat($format, $time, $tz, $locale);
+ }
+
+ /**
+ * Make a Carbon instance from given variable if possible.
+ *
+ * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
+ * and recurrences). Throw an exception for invalid format, but otherwise return null.
+ *
+ * @param mixed $var
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static|null
+ */
+ public static function make($var)
+ {
+ if ($var instanceof DateTimeInterface) {
+ return static::instance($var);
+ }
+
+ $date = null;
+
+ if (\is_string($var)) {
+ $var = trim($var);
+
+ if (!preg_match('/^P[0-9T]/', $var) &&
+ !preg_match('/^R[0-9]/', $var) &&
+ preg_match('/[a-z0-9]/i', $var)
+ ) {
+ $date = static::parse($var);
+ }
+ }
+
+ return $date;
+ }
+
+ /**
+ * Set last errors.
+ *
+ * @param array $lastErrors
+ *
+ * @return void
+ */
+ private static function setLastErrors(array $lastErrors)
+ {
+ static::$lastErrors = $lastErrors;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ #[ReturnTypeWillChange]
+ public static function getLastErrors()
+ {
+ return static::$lastErrors;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Date.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Date.php
new file mode 100644
index 0000000..07ac0dd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Date.php
@@ -0,0 +1,2662 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use BadMethodCallException;
+use Carbon\Carbon;
+use Carbon\CarbonInterface;
+use Carbon\CarbonPeriod;
+use Carbon\CarbonTimeZone;
+use Carbon\Exceptions\BadComparisonUnitException;
+use Carbon\Exceptions\ImmutableException;
+use Carbon\Exceptions\InvalidTimeZoneException;
+use Carbon\Exceptions\InvalidTypeException;
+use Carbon\Exceptions\UnknownGetterException;
+use Carbon\Exceptions\UnknownMethodException;
+use Carbon\Exceptions\UnknownSetterException;
+use Carbon\Exceptions\UnknownUnitException;
+use Closure;
+use DateInterval;
+use DatePeriod;
+use DateTime;
+use DateTimeImmutable;
+use DateTimeInterface;
+use DateTimeZone;
+use InvalidArgumentException;
+use ReflectionException;
+use ReturnTypeWillChange;
+use Throwable;
+
+/**
+ * A simple API extension for DateTime.
+ *
+ * <autodoc generated by `composer phpdoc`>
+ *
+ * @property int $year
+ * @property int $yearIso
+ * @property int $month
+ * @property int $day
+ * @property int $hour
+ * @property int $minute
+ * @property int $second
+ * @property int $micro
+ * @property int $microsecond
+ * @property int|float|string $timestamp seconds since the Unix Epoch
+ * @property string $englishDayOfWeek the day of week in English
+ * @property string $shortEnglishDayOfWeek the abbreviated day of week in English
+ * @property string $englishMonth the month in English
+ * @property string $shortEnglishMonth the abbreviated month in English
+ * @property string $localeDayOfWeek the day of week in current locale LC_TIME
+ * @property string $shortLocaleDayOfWeek the abbreviated day of week in current locale LC_TIME
+ * @property string $localeMonth the month in current locale LC_TIME
+ * @property string $shortLocaleMonth the abbreviated month in current locale LC_TIME
+ * @property int $milliseconds
+ * @property int $millisecond
+ * @property int $milli
+ * @property int $week 1 through 53
+ * @property int $isoWeek 1 through 53
+ * @property int $weekYear year according to week format
+ * @property int $isoWeekYear year according to ISO week format
+ * @property int $dayOfYear 1 through 366
+ * @property int $age does a diffInYears() with default parameters
+ * @property int $offset the timezone offset in seconds from UTC
+ * @property int $offsetMinutes the timezone offset in minutes from UTC
+ * @property int $offsetHours the timezone offset in hours from UTC
+ * @property CarbonTimeZone $timezone the current timezone
+ * @property CarbonTimeZone $tz alias of $timezone
+ * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
+ * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday)
+ * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
+ * @property-read int $daysInMonth number of days in the given month
+ * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
+ * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
+ * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
+ * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
+ * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language
+ * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
+ * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
+ * @property-read int $noZeroHour current hour from 1 to 24
+ * @property-read int $weeksInYear 51 through 53
+ * @property-read int $isoWeeksInYear 51 through 53
+ * @property-read int $weekOfMonth 1 through 5
+ * @property-read int $weekNumberInMonth 1 through 5
+ * @property-read int $firstWeekDay 0 through 6
+ * @property-read int $lastWeekDay 0 through 6
+ * @property-read int $daysInYear 365 or 366
+ * @property-read int $quarter the quarter of this instance, 1 - 4
+ * @property-read int $decade the decade of this instance
+ * @property-read int $century the century of this instance
+ * @property-read int $millennium the millennium of this instance
+ * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
+ * @property-read bool $local checks if the timezone is local, true if local, false otherwise
+ * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
+ * @property-read string $timezoneName the current timezone name
+ * @property-read string $tzName alias of $timezoneName
+ * @property-read string $locale locale of the current instance
+ *
+ * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
+ * @method bool isLocal() Check if the current instance has non-UTC timezone.
+ * @method bool isValid() Check if the current instance is a valid date.
+ * @method bool isDST() Check if the current instance is in a daylight saving time.
+ * @method bool isSunday() Checks if the instance day is sunday.
+ * @method bool isMonday() Checks if the instance day is monday.
+ * @method bool isTuesday() Checks if the instance day is tuesday.
+ * @method bool isWednesday() Checks if the instance day is wednesday.
+ * @method bool isThursday() Checks if the instance day is thursday.
+ * @method bool isFriday() Checks if the instance day is friday.
+ * @method bool isSaturday() Checks if the instance day is saturday.
+ * @method bool isSameYear(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment.
+ * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year.
+ * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year.
+ * @method bool isSameWeek(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment.
+ * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week.
+ * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week.
+ * @method bool isSameDay(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment.
+ * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day.
+ * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day.
+ * @method bool isSameHour(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment.
+ * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour.
+ * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour.
+ * @method bool isSameMinute(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment.
+ * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute.
+ * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute.
+ * @method bool isSameSecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment.
+ * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second.
+ * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second.
+ * @method bool isSameMicro(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment.
+ * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond.
+ * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond.
+ * @method bool isSameMicrosecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment.
+ * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond.
+ * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond.
+ * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment.
+ * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month.
+ * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month.
+ * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment.
+ * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter.
+ * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter.
+ * @method bool isSameDecade(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment.
+ * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade.
+ * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade.
+ * @method bool isSameCentury(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment.
+ * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century.
+ * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century.
+ * @method bool isSameMillennium(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
+ * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment.
+ * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium.
+ * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium.
+ * @method CarbonInterface years(int $value) Set current instance year to the given value.
+ * @method CarbonInterface year(int $value) Set current instance year to the given value.
+ * @method CarbonInterface setYears(int $value) Set current instance year to the given value.
+ * @method CarbonInterface setYear(int $value) Set current instance year to the given value.
+ * @method CarbonInterface months(int $value) Set current instance month to the given value.
+ * @method CarbonInterface month(int $value) Set current instance month to the given value.
+ * @method CarbonInterface setMonths(int $value) Set current instance month to the given value.
+ * @method CarbonInterface setMonth(int $value) Set current instance month to the given value.
+ * @method CarbonInterface days(int $value) Set current instance day to the given value.
+ * @method CarbonInterface day(int $value) Set current instance day to the given value.
+ * @method CarbonInterface setDays(int $value) Set current instance day to the given value.
+ * @method CarbonInterface setDay(int $value) Set current instance day to the given value.
+ * @method CarbonInterface hours(int $value) Set current instance hour to the given value.
+ * @method CarbonInterface hour(int $value) Set current instance hour to the given value.
+ * @method CarbonInterface setHours(int $value) Set current instance hour to the given value.
+ * @method CarbonInterface setHour(int $value) Set current instance hour to the given value.
+ * @method CarbonInterface minutes(int $value) Set current instance minute to the given value.
+ * @method CarbonInterface minute(int $value) Set current instance minute to the given value.
+ * @method CarbonInterface setMinutes(int $value) Set current instance minute to the given value.
+ * @method CarbonInterface setMinute(int $value) Set current instance minute to the given value.
+ * @method CarbonInterface seconds(int $value) Set current instance second to the given value.
+ * @method CarbonInterface second(int $value) Set current instance second to the given value.
+ * @method CarbonInterface setSeconds(int $value) Set current instance second to the given value.
+ * @method CarbonInterface setSecond(int $value) Set current instance second to the given value.
+ * @method CarbonInterface millis(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface milli(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface setMillis(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface setMilli(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface milliseconds(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface millisecond(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface setMilliseconds(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface setMillisecond(int $value) Set current instance millisecond to the given value.
+ * @method CarbonInterface micros(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface micro(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface setMicros(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface setMicro(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface microseconds(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface microsecond(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface setMicroseconds(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface setMicrosecond(int $value) Set current instance microsecond to the given value.
+ * @method CarbonInterface addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addYear() Add one year to the instance (using date interval).
+ * @method CarbonInterface subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subYear() Sub one year to the instance (using date interval).
+ * @method CarbonInterface addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMonth() Add one month to the instance (using date interval).
+ * @method CarbonInterface subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMonth() Sub one month to the instance (using date interval).
+ * @method CarbonInterface addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addDay() Add one day to the instance (using date interval).
+ * @method CarbonInterface subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subDay() Sub one day to the instance (using date interval).
+ * @method CarbonInterface addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addHour() Add one hour to the instance (using date interval).
+ * @method CarbonInterface subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subHour() Sub one hour to the instance (using date interval).
+ * @method CarbonInterface addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMinute() Add one minute to the instance (using date interval).
+ * @method CarbonInterface subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMinute() Sub one minute to the instance (using date interval).
+ * @method CarbonInterface addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addSecond() Add one second to the instance (using date interval).
+ * @method CarbonInterface subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subSecond() Sub one second to the instance (using date interval).
+ * @method CarbonInterface addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMilli() Add one millisecond to the instance (using date interval).
+ * @method CarbonInterface subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMilli() Sub one millisecond to the instance (using date interval).
+ * @method CarbonInterface addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMillisecond() Add one millisecond to the instance (using date interval).
+ * @method CarbonInterface subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMillisecond() Sub one millisecond to the instance (using date interval).
+ * @method CarbonInterface addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMicro() Add one microsecond to the instance (using date interval).
+ * @method CarbonInterface subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMicro() Sub one microsecond to the instance (using date interval).
+ * @method CarbonInterface addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMicrosecond() Add one microsecond to the instance (using date interval).
+ * @method CarbonInterface subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMicrosecond() Sub one microsecond to the instance (using date interval).
+ * @method CarbonInterface addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addMillennium() Add one millennium to the instance (using date interval).
+ * @method CarbonInterface subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subMillennium() Sub one millennium to the instance (using date interval).
+ * @method CarbonInterface addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addCentury() Add one century to the instance (using date interval).
+ * @method CarbonInterface subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subCentury() Sub one century to the instance (using date interval).
+ * @method CarbonInterface addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addDecade() Add one decade to the instance (using date interval).
+ * @method CarbonInterface subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subDecade() Sub one decade to the instance (using date interval).
+ * @method CarbonInterface addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addQuarter() Add one quarter to the instance (using date interval).
+ * @method CarbonInterface subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subQuarter() Sub one quarter to the instance (using date interval).
+ * @method CarbonInterface addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
+ * @method CarbonInterface addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
+ * @method CarbonInterface addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addWeek() Add one week to the instance (using date interval).
+ * @method CarbonInterface subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subWeek() Sub one week to the instance (using date interval).
+ * @method CarbonInterface addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface addWeekday() Add one weekday to the instance (using date interval).
+ * @method CarbonInterface subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval).
+ * @method CarbonInterface subWeekday() Sub one weekday to the instance (using date interval).
+ * @method CarbonInterface addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMicro() Add one microsecond to the instance (using timestamp).
+ * @method CarbonInterface subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMicro() Sub one microsecond to the instance (using timestamp).
+ * @method CarbonPeriod microsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
+ * @method CarbonInterface addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMicrosecond() Add one microsecond to the instance (using timestamp).
+ * @method CarbonInterface subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMicrosecond() Sub one microsecond to the instance (using timestamp).
+ * @method CarbonPeriod microsecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
+ * @method CarbonInterface addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMilli() Add one millisecond to the instance (using timestamp).
+ * @method CarbonInterface subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMilli() Sub one millisecond to the instance (using timestamp).
+ * @method CarbonPeriod millisUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
+ * @method CarbonInterface addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMillisecond() Add one millisecond to the instance (using timestamp).
+ * @method CarbonInterface subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMillisecond() Sub one millisecond to the instance (using timestamp).
+ * @method CarbonPeriod millisecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
+ * @method CarbonInterface addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealSecond() Add one second to the instance (using timestamp).
+ * @method CarbonInterface subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealSecond() Sub one second to the instance (using timestamp).
+ * @method CarbonPeriod secondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given.
+ * @method CarbonInterface addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMinute() Add one minute to the instance (using timestamp).
+ * @method CarbonInterface subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMinute() Sub one minute to the instance (using timestamp).
+ * @method CarbonPeriod minutesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given.
+ * @method CarbonInterface addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealHour() Add one hour to the instance (using timestamp).
+ * @method CarbonInterface subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealHour() Sub one hour to the instance (using timestamp).
+ * @method CarbonPeriod hoursUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given.
+ * @method CarbonInterface addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealDay() Add one day to the instance (using timestamp).
+ * @method CarbonInterface subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealDay() Sub one day to the instance (using timestamp).
+ * @method CarbonPeriod daysUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given.
+ * @method CarbonInterface addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealWeek() Add one week to the instance (using timestamp).
+ * @method CarbonInterface subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealWeek() Sub one week to the instance (using timestamp).
+ * @method CarbonPeriod weeksUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given.
+ * @method CarbonInterface addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMonth() Add one month to the instance (using timestamp).
+ * @method CarbonInterface subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMonth() Sub one month to the instance (using timestamp).
+ * @method CarbonPeriod monthsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given.
+ * @method CarbonInterface addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealQuarter() Add one quarter to the instance (using timestamp).
+ * @method CarbonInterface subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealQuarter() Sub one quarter to the instance (using timestamp).
+ * @method CarbonPeriod quartersUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given.
+ * @method CarbonInterface addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealYear() Add one year to the instance (using timestamp).
+ * @method CarbonInterface subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealYear() Sub one year to the instance (using timestamp).
+ * @method CarbonPeriod yearsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given.
+ * @method CarbonInterface addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealDecade() Add one decade to the instance (using timestamp).
+ * @method CarbonInterface subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealDecade() Sub one decade to the instance (using timestamp).
+ * @method CarbonPeriod decadesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given.
+ * @method CarbonInterface addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealCentury() Add one century to the instance (using timestamp).
+ * @method CarbonInterface subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealCentury() Sub one century to the instance (using timestamp).
+ * @method CarbonPeriod centuriesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given.
+ * @method CarbonInterface addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface addRealMillennium() Add one millennium to the instance (using timestamp).
+ * @method CarbonInterface subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp).
+ * @method CarbonInterface subRealMillennium() Sub one millennium to the instance (using timestamp).
+ * @method CarbonPeriod millenniaUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given.
+ * @method CarbonInterface roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method CarbonInterface roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
+ * @method CarbonInterface floorYear(float $precision = 1) Truncate the current instance year with given precision.
+ * @method CarbonInterface floorYears(float $precision = 1) Truncate the current instance year with given precision.
+ * @method CarbonInterface ceilYear(float $precision = 1) Ceil the current instance year with given precision.
+ * @method CarbonInterface ceilYears(float $precision = 1) Ceil the current instance year with given precision.
+ * @method CarbonInterface roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method CarbonInterface roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
+ * @method CarbonInterface floorMonth(float $precision = 1) Truncate the current instance month with given precision.
+ * @method CarbonInterface floorMonths(float $precision = 1) Truncate the current instance month with given precision.
+ * @method CarbonInterface ceilMonth(float $precision = 1) Ceil the current instance month with given precision.
+ * @method CarbonInterface ceilMonths(float $precision = 1) Ceil the current instance month with given precision.
+ * @method CarbonInterface roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method CarbonInterface roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
+ * @method CarbonInterface floorDay(float $precision = 1) Truncate the current instance day with given precision.
+ * @method CarbonInterface floorDays(float $precision = 1) Truncate the current instance day with given precision.
+ * @method CarbonInterface ceilDay(float $precision = 1) Ceil the current instance day with given precision.
+ * @method CarbonInterface ceilDays(float $precision = 1) Ceil the current instance day with given precision.
+ * @method CarbonInterface roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method CarbonInterface roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
+ * @method CarbonInterface floorHour(float $precision = 1) Truncate the current instance hour with given precision.
+ * @method CarbonInterface floorHours(float $precision = 1) Truncate the current instance hour with given precision.
+ * @method CarbonInterface ceilHour(float $precision = 1) Ceil the current instance hour with given precision.
+ * @method CarbonInterface ceilHours(float $precision = 1) Ceil the current instance hour with given precision.
+ * @method CarbonInterface roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method CarbonInterface roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
+ * @method CarbonInterface floorMinute(float $precision = 1) Truncate the current instance minute with given precision.
+ * @method CarbonInterface floorMinutes(float $precision = 1) Truncate the current instance minute with given precision.
+ * @method CarbonInterface ceilMinute(float $precision = 1) Ceil the current instance minute with given precision.
+ * @method CarbonInterface ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision.
+ * @method CarbonInterface roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method CarbonInterface roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
+ * @method CarbonInterface floorSecond(float $precision = 1) Truncate the current instance second with given precision.
+ * @method CarbonInterface floorSeconds(float $precision = 1) Truncate the current instance second with given precision.
+ * @method CarbonInterface ceilSecond(float $precision = 1) Ceil the current instance second with given precision.
+ * @method CarbonInterface ceilSeconds(float $precision = 1) Ceil the current instance second with given precision.
+ * @method CarbonInterface roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method CarbonInterface roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
+ * @method CarbonInterface floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method CarbonInterface floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision.
+ * @method CarbonInterface ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method CarbonInterface ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision.
+ * @method CarbonInterface roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method CarbonInterface roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
+ * @method CarbonInterface floorCentury(float $precision = 1) Truncate the current instance century with given precision.
+ * @method CarbonInterface floorCenturies(float $precision = 1) Truncate the current instance century with given precision.
+ * @method CarbonInterface ceilCentury(float $precision = 1) Ceil the current instance century with given precision.
+ * @method CarbonInterface ceilCenturies(float $precision = 1) Ceil the current instance century with given precision.
+ * @method CarbonInterface roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method CarbonInterface roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
+ * @method CarbonInterface floorDecade(float $precision = 1) Truncate the current instance decade with given precision.
+ * @method CarbonInterface floorDecades(float $precision = 1) Truncate the current instance decade with given precision.
+ * @method CarbonInterface ceilDecade(float $precision = 1) Ceil the current instance decade with given precision.
+ * @method CarbonInterface ceilDecades(float $precision = 1) Ceil the current instance decade with given precision.
+ * @method CarbonInterface roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method CarbonInterface roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
+ * @method CarbonInterface floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method CarbonInterface floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision.
+ * @method CarbonInterface ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method CarbonInterface ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision.
+ * @method CarbonInterface roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method CarbonInterface roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
+ * @method CarbonInterface floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method CarbonInterface floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision.
+ * @method CarbonInterface ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method CarbonInterface ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision.
+ * @method CarbonInterface roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method CarbonInterface roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
+ * @method CarbonInterface floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method CarbonInterface floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision.
+ * @method CarbonInterface ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision.
+ * @method CarbonInterface ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision.
+ * @method string shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ * @method string longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
+ *
+ * </autodoc>
+ */
+trait Date
+{
+ use Boundaries;
+ use Comparison;
+ use Converter;
+ use Creator;
+ use Difference;
+ use Macro;
+ use Modifiers;
+ use Mutability;
+ use ObjectInitialisation;
+ use Options;
+ use Rounding;
+ use Serialization;
+ use Test;
+ use Timestamp;
+ use Units;
+ use Week;
+
+ /**
+ * Names of days of the week.
+ *
+ * @var array
+ */
+ protected static $days = [
+ // @call isDayOfWeek
+ CarbonInterface::SUNDAY => 'Sunday',
+ // @call isDayOfWeek
+ CarbonInterface::MONDAY => 'Monday',
+ // @call isDayOfWeek
+ CarbonInterface::TUESDAY => 'Tuesday',
+ // @call isDayOfWeek
+ CarbonInterface::WEDNESDAY => 'Wednesday',
+ // @call isDayOfWeek
+ CarbonInterface::THURSDAY => 'Thursday',
+ // @call isDayOfWeek
+ CarbonInterface::FRIDAY => 'Friday',
+ // @call isDayOfWeek
+ CarbonInterface::SATURDAY => 'Saturday',
+ ];
+
+ /**
+ * Will UTF8 encoding be used to print localized date/time ?
+ *
+ * @var bool
+ */
+ protected static $utf8 = false;
+
+ /**
+ * List of unit and magic methods associated as doc-comments.
+ *
+ * @var array
+ */
+ protected static $units = [
+ // @call setUnit
+ // @call addUnit
+ 'year',
+ // @call setUnit
+ // @call addUnit
+ 'month',
+ // @call setUnit
+ // @call addUnit
+ 'day',
+ // @call setUnit
+ // @call addUnit
+ 'hour',
+ // @call setUnit
+ // @call addUnit
+ 'minute',
+ // @call setUnit
+ // @call addUnit
+ 'second',
+ // @call setUnit
+ // @call addUnit
+ 'milli',
+ // @call setUnit
+ // @call addUnit
+ 'millisecond',
+ // @call setUnit
+ // @call addUnit
+ 'micro',
+ // @call setUnit
+ // @call addUnit
+ 'microsecond',
+ ];
+
+ /**
+ * Creates a DateTimeZone from a string, DateTimeZone or integer offset.
+ *
+ * @param DateTimeZone|string|int|null $object original value to get CarbonTimeZone from it.
+ * @param DateTimeZone|string|int|null $objectDump dump of the object for error messages.
+ *
+ * @throws InvalidTimeZoneException
+ *
+ * @return CarbonTimeZone|false
+ */
+ protected static function safeCreateDateTimeZone($object, $objectDump = null)
+ {
+ return CarbonTimeZone::instance($object, $objectDump);
+ }
+
+ /**
+ * Get the TimeZone associated with the Carbon instance (as CarbonTimeZone).
+ *
+ * @return CarbonTimeZone
+ *
+ * @link https://php.net/manual/en/datetime.gettimezone.php
+ */
+ #[ReturnTypeWillChange]
+ public function getTimezone()
+ {
+ return CarbonTimeZone::instance(parent::getTimezone());
+ }
+
+ /**
+ * List of minimum and maximums for each unit.
+ *
+ * @return array
+ */
+ protected static function getRangesByUnit()
+ {
+ return [
+ // @call roundUnit
+ 'year' => [1, 9999],
+ // @call roundUnit
+ 'month' => [1, static::MONTHS_PER_YEAR],
+ // @call roundUnit
+ 'day' => [1, 31],
+ // @call roundUnit
+ 'hour' => [0, static::HOURS_PER_DAY - 1],
+ // @call roundUnit
+ 'minute' => [0, static::MINUTES_PER_HOUR - 1],
+ // @call roundUnit
+ 'second' => [0, static::SECONDS_PER_MINUTE - 1],
+ ];
+ }
+
+ /**
+ * Get a copy of the instance.
+ *
+ * @return static
+ */
+ public function copy()
+ {
+ return clone $this;
+ }
+
+ /**
+ * @alias copy
+ *
+ * Get a copy of the instance.
+ *
+ * @return static
+ */
+ public function clone()
+ {
+ return clone $this;
+ }
+
+ /**
+ * Clone the current instance if it's mutable.
+ *
+ * This method is convenient to ensure you don't mutate the initial object
+ * but avoid to make a useless copy of it if it's already immutable.
+ *
+ * @return static
+ */
+ public function avoidMutation(): self
+ {
+ if ($this instanceof DateTimeImmutable) {
+ return $this;
+ }
+
+ return clone $this;
+ }
+
+ /**
+ * Returns a present instance in the same timezone.
+ *
+ * @return static
+ */
+ public function nowWithSameTz()
+ {
+ return static::now($this->getTimezone());
+ }
+
+ /**
+ * Throws an exception if the given object is not a DateTime and does not implement DateTimeInterface.
+ *
+ * @param mixed $date
+ * @param string|array $other
+ *
+ * @throws InvalidTypeException
+ */
+ protected static function expectDateTime($date, $other = [])
+ {
+ $message = 'Expected ';
+ foreach ((array) $other as $expect) {
+ $message .= "$expect, ";
+ }
+
+ if (!$date instanceof DateTime && !$date instanceof DateTimeInterface) {
+ throw new InvalidTypeException(
+ $message.'DateTime or DateTimeInterface, '.
+ (\is_object($date) ? \get_class($date) : \gettype($date)).' given'
+ );
+ }
+ }
+
+ /**
+ * Return the Carbon instance passed through, a now instance in the same timezone
+ * if null given or parse the input if string given.
+ *
+ * @param Carbon|DateTimeInterface|string|null $date
+ *
+ * @return static
+ */
+ protected function resolveCarbon($date = null)
+ {
+ if (!$date) {
+ return $this->nowWithSameTz();
+ }
+
+ if (\is_string($date)) {
+ return static::parse($date, $this->getTimezone());
+ }
+
+ static::expectDateTime($date, ['null', 'string']);
+
+ return $date instanceof self ? $date : static::instance($date);
+ }
+
+ /**
+ * Return the Carbon instance passed through, a now instance in UTC
+ * if null given or parse the input if string given (using current timezone
+ * then switching to UTC).
+ *
+ * @param Carbon|DateTimeInterface|string|null $date
+ *
+ * @return static
+ */
+ protected function resolveUTC($date = null): self
+ {
+ if (!$date) {
+ return static::now('UTC');
+ }
+
+ if (\is_string($date)) {
+ return static::parse($date, $this->getTimezone())->utc();
+ }
+
+ static::expectDateTime($date, ['null', 'string']);
+
+ return $date instanceof self ? $date : static::instance($date)->utc();
+ }
+
+ /**
+ * Return the Carbon instance passed through, a now instance in the same timezone
+ * if null given or parse the input if string given.
+ *
+ * @param Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|DateTimeInterface|string|null $date
+ *
+ * @return static
+ */
+ public function carbonize($date = null)
+ {
+ if ($date instanceof DateInterval) {
+ return $this->avoidMutation()->add($date);
+ }
+
+ if ($date instanceof DatePeriod || $date instanceof CarbonPeriod) {
+ $date = $date->getStartDate();
+ }
+
+ return $this->resolveCarbon($date);
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ ///////////////////////// GETTERS AND SETTERS /////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Get a part of the Carbon object
+ *
+ * @param string $name
+ *
+ * @throws UnknownGetterException
+ *
+ * @return string|int|bool|DateTimeZone|null
+ */
+ public function __get($name)
+ {
+ return $this->get($name);
+ }
+
+ /**
+ * Get a part of the Carbon object
+ *
+ * @param string $name
+ *
+ * @throws UnknownGetterException
+ *
+ * @return string|int|bool|DateTimeZone|null
+ */
+ public function get($name)
+ {
+ static $formats = [
+ // @property int
+ 'year' => 'Y',
+ // @property int
+ 'yearIso' => 'o',
+ // @property int
+ // @call isSameUnit
+ 'month' => 'n',
+ // @property int
+ 'day' => 'j',
+ // @property int
+ 'hour' => 'G',
+ // @property int
+ 'minute' => 'i',
+ // @property int
+ 'second' => 's',
+ // @property int
+ 'micro' => 'u',
+ // @property int
+ 'microsecond' => 'u',
+ // @property-read int 0 (for Sunday) through 6 (for Saturday)
+ 'dayOfWeek' => 'w',
+ // @property-read int 1 (for Monday) through 7 (for Sunday)
+ 'dayOfWeekIso' => 'N',
+ // @property-read int ISO-8601 week number of year, weeks starting on Monday
+ 'weekOfYear' => 'W',
+ // @property-read int number of days in the given month
+ 'daysInMonth' => 't',
+ // @property int|float|string seconds since the Unix Epoch
+ 'timestamp' => 'U',
+ // @property-read string "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
+ 'latinMeridiem' => 'a',
+ // @property-read string "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
+ 'latinUpperMeridiem' => 'A',
+ // @property string the day of week in English
+ 'englishDayOfWeek' => 'l',
+ // @property string the abbreviated day of week in English
+ 'shortEnglishDayOfWeek' => 'D',
+ // @property string the month in English
+ 'englishMonth' => 'F',
+ // @property string the abbreviated month in English
+ 'shortEnglishMonth' => 'M',
+ // @property string the day of week in current locale LC_TIME
+ 'localeDayOfWeek' => '%A',
+ // @property string the abbreviated day of week in current locale LC_TIME
+ 'shortLocaleDayOfWeek' => '%a',
+ // @property string the month in current locale LC_TIME
+ 'localeMonth' => '%B',
+ // @property string the abbreviated month in current locale LC_TIME
+ 'shortLocaleMonth' => '%b',
+ // @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
+ 'timezoneAbbreviatedName' => 'T',
+ // @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
+ 'tzAbbrName' => 'T',
+ ];
+
+ switch (true) {
+ case isset($formats[$name]):
+ $format = $formats[$name];
+ $method = str_starts_with($format, '%') ? 'formatLocalized' : 'rawFormat';
+ $value = $this->$method($format);
+
+ return is_numeric($value) ? (int) $value : $value;
+
+ // @property-read string long name of weekday translated according to Carbon locale, in english if no translation available for current language
+ case $name === 'dayName':
+ return $this->getTranslatedDayName();
+ // @property-read string short name of weekday translated according to Carbon locale, in english if no translation available for current language
+ case $name === 'shortDayName':
+ return $this->getTranslatedShortDayName();
+ // @property-read string very short name of weekday translated according to Carbon locale, in english if no translation available for current language
+ case $name === 'minDayName':
+ return $this->getTranslatedMinDayName();
+ // @property-read string long name of month translated according to Carbon locale, in english if no translation available for current language
+ case $name === 'monthName':
+ return $this->getTranslatedMonthName();
+ // @property-read string short name of month translated according to Carbon locale, in english if no translation available for current language
+ case $name === 'shortMonthName':
+ return $this->getTranslatedShortMonthName();
+ // @property-read string lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
+ case $name === 'meridiem':
+ return $this->meridiem(true);
+ // @property-read string uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
+ case $name === 'upperMeridiem':
+ return $this->meridiem();
+ // @property-read int current hour from 1 to 24
+ case $name === 'noZeroHour':
+ return $this->hour ?: 24;
+ // @property int
+ case $name === 'milliseconds':
+ // @property int
+ case $name === 'millisecond':
+ // @property int
+ case $name === 'milli':
+ return (int) floor($this->rawFormat('u') / 1000);
+
+ // @property int 1 through 53
+ case $name === 'week':
+ return (int) $this->week();
+
+ // @property int 1 through 53
+ case $name === 'isoWeek':
+ return (int) $this->isoWeek();
+
+ // @property int year according to week format
+ case $name === 'weekYear':
+ return (int) $this->weekYear();
+
+ // @property int year according to ISO week format
+ case $name === 'isoWeekYear':
+ return (int) $this->isoWeekYear();
+
+ // @property-read int 51 through 53
+ case $name === 'weeksInYear':
+ return $this->weeksInYear();
+
+ // @property-read int 51 through 53
+ case $name === 'isoWeeksInYear':
+ return $this->isoWeeksInYear();
+
+ // @property-read int 1 through 5
+ case $name === 'weekOfMonth':
+ return (int) ceil($this->day / static::DAYS_PER_WEEK);
+
+ // @property-read int 1 through 5
+ case $name === 'weekNumberInMonth':
+ return (int) ceil(($this->day + $this->avoidMutation()->startOfMonth()->dayOfWeekIso - 1) / static::DAYS_PER_WEEK);
+
+ // @property-read int 0 through 6
+ case $name === 'firstWeekDay':
+ return $this->localTranslator ? ($this->getTranslationMessage('first_day_of_week') ?? 0) : static::getWeekStartsAt();
+
+ // @property-read int 0 through 6
+ case $name === 'lastWeekDay':
+ return $this->localTranslator ? (($this->getTranslationMessage('first_day_of_week') ?? 0) + static::DAYS_PER_WEEK - 1) % static::DAYS_PER_WEEK : static::getWeekEndsAt();
+
+ // @property int 1 through 366
+ case $name === 'dayOfYear':
+ return 1 + (int) ($this->rawFormat('z'));
+
+ // @property-read int 365 or 366
+ case $name === 'daysInYear':
+ return $this->isLeapYear() ? 366 : 365;
+
+ // @property int does a diffInYears() with default parameters
+ case $name === 'age':
+ return $this->diffInYears();
+
+ // @property-read int the quarter of this instance, 1 - 4
+ // @call isSameUnit
+ case $name === 'quarter':
+ return (int) ceil($this->month / static::MONTHS_PER_QUARTER);
+
+ // @property-read int the decade of this instance
+ // @call isSameUnit
+ case $name === 'decade':
+ return (int) ceil($this->year / static::YEARS_PER_DECADE);
+
+ // @property-read int the century of this instance
+ // @call isSameUnit
+ case $name === 'century':
+ $factor = 1;
+ $year = $this->year;
+ if ($year < 0) {
+ $year = -$year;
+ $factor = -1;
+ }
+
+ return (int) ($factor * ceil($year / static::YEARS_PER_CENTURY));
+
+ // @property-read int the millennium of this instance
+ // @call isSameUnit
+ case $name === 'millennium':
+ $factor = 1;
+ $year = $this->year;
+ if ($year < 0) {
+ $year = -$year;
+ $factor = -1;
+ }
+
+ return (int) ($factor * ceil($year / static::YEARS_PER_MILLENNIUM));
+
+ // @property int the timezone offset in seconds from UTC
+ case $name === 'offset':
+ return $this->getOffset();
+
+ // @property int the timezone offset in minutes from UTC
+ case $name === 'offsetMinutes':
+ return $this->getOffset() / static::SECONDS_PER_MINUTE;
+
+ // @property int the timezone offset in hours from UTC
+ case $name === 'offsetHours':
+ return $this->getOffset() / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR;
+
+ // @property-read bool daylight savings time indicator, true if DST, false otherwise
+ case $name === 'dst':
+ return $this->rawFormat('I') === '1';
+
+ // @property-read bool checks if the timezone is local, true if local, false otherwise
+ case $name === 'local':
+ return $this->getOffset() === $this->avoidMutation()->setTimezone(date_default_timezone_get())->getOffset();
+
+ // @property-read bool checks if the timezone is UTC, true if UTC, false otherwise
+ case $name === 'utc':
+ return $this->getOffset() === 0;
+
+ // @property CarbonTimeZone $timezone the current timezone
+ // @property CarbonTimeZone $tz alias of $timezone
+ case $name === 'timezone' || $name === 'tz':
+ return CarbonTimeZone::instance($this->getTimezone());
+
+ // @property-read string $timezoneName the current timezone name
+ // @property-read string $tzName alias of $timezoneName
+ case $name === 'timezoneName' || $name === 'tzName':
+ return $this->getTimezone()->getName();
+
+ // @property-read string locale of the current instance
+ case $name === 'locale':
+ return $this->getTranslatorLocale();
+
+ default:
+ $macro = $this->getLocalMacro('get'.ucfirst($name));
+
+ if ($macro) {
+ return $this->executeCallableWithContext($macro);
+ }
+
+ throw new UnknownGetterException($name);
+ }
+ }
+
+ /**
+ * Check if an attribute exists on the object
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function __isset($name)
+ {
+ try {
+ $this->__get($name);
+ } catch (UnknownGetterException | ReflectionException $e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Set a part of the Carbon object
+ *
+ * @param string $name
+ * @param string|int|DateTimeZone $value
+ *
+ * @throws UnknownSetterException|ReflectionException
+ *
+ * @return void
+ */
+ public function __set($name, $value)
+ {
+ if ($this->constructedObjectId === spl_object_hash($this)) {
+ $this->set($name, $value);
+
+ return;
+ }
+
+ $this->$name = $value;
+ }
+
+ /**
+ * Set a part of the Carbon object
+ *
+ * @param string|array $name
+ * @param string|int|DateTimeZone $value
+ *
+ * @throws ImmutableException|UnknownSetterException
+ *
+ * @return $this
+ */
+ public function set($name, $value = null)
+ {
+ if ($this->isImmutable()) {
+ throw new ImmutableException(sprintf('%s class', static::class));
+ }
+
+ if (\is_array($name)) {
+ foreach ($name as $key => $value) {
+ $this->set($key, $value);
+ }
+
+ return $this;
+ }
+
+ switch ($name) {
+ case 'milliseconds':
+ case 'millisecond':
+ case 'milli':
+ case 'microseconds':
+ case 'microsecond':
+ case 'micro':
+ if (str_starts_with($name, 'milli')) {
+ $value *= 1000;
+ }
+
+ while ($value < 0) {
+ $this->subSecond();
+ $value += static::MICROSECONDS_PER_SECOND;
+ }
+
+ while ($value >= static::MICROSECONDS_PER_SECOND) {
+ $this->addSecond();
+ $value -= static::MICROSECONDS_PER_SECOND;
+ }
+
+ $this->modify($this->rawFormat('H:i:s.').str_pad((string) round($value), 6, '0', STR_PAD_LEFT));
+
+ break;
+
+ case 'year':
+ case 'month':
+ case 'day':
+ case 'hour':
+ case 'minute':
+ case 'second':
+ [$year, $month, $day, $hour, $minute, $second] = array_map('intval', explode('-', $this->rawFormat('Y-n-j-G-i-s')));
+ $$name = $value;
+ $this->setDateTime($year, $month, $day, $hour, $minute, $second);
+
+ break;
+
+ case 'week':
+ $this->week($value);
+
+ break;
+
+ case 'isoWeek':
+ $this->isoWeek($value);
+
+ break;
+
+ case 'weekYear':
+ $this->weekYear($value);
+
+ break;
+
+ case 'isoWeekYear':
+ $this->isoWeekYear($value);
+
+ break;
+
+ case 'dayOfYear':
+ $this->addDays($value - $this->dayOfYear);
+
+ break;
+
+ case 'timestamp':
+ $this->setTimestamp($value);
+
+ break;
+
+ case 'offset':
+ $this->setTimezone(static::safeCreateDateTimeZone($value / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR));
+
+ break;
+
+ case 'offsetMinutes':
+ $this->setTimezone(static::safeCreateDateTimeZone($value / static::MINUTES_PER_HOUR));
+
+ break;
+
+ case 'offsetHours':
+ $this->setTimezone(static::safeCreateDateTimeZone($value));
+
+ break;
+
+ case 'timezone':
+ case 'tz':
+ $this->setTimezone($value);
+
+ break;
+
+ default:
+ $macro = $this->getLocalMacro('set'.ucfirst($name));
+
+ if ($macro) {
+ $this->executeCallableWithContext($macro, $value);
+
+ break;
+ }
+
+ if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
+ throw new UnknownSetterException($name);
+ }
+
+ $this->$name = $value;
+ }
+
+ return $this;
+ }
+
+ protected function getTranslatedFormByRegExp($baseKey, $keySuffix, $context, $subKey, $defaultValue)
+ {
+ $key = $baseKey.$keySuffix;
+ $standaloneKey = "${key}_standalone";
+ $baseTranslation = $this->getTranslationMessage($key);
+
+ if ($baseTranslation instanceof Closure) {
+ return $baseTranslation($this, $context, $subKey) ?: $defaultValue;
+ }
+
+ if (
+ $this->getTranslationMessage("$standaloneKey.$subKey") &&
+ (!$context || ($regExp = $this->getTranslationMessage("${baseKey}_regexp")) && !preg_match($regExp, $context))
+ ) {
+ $key = $standaloneKey;
+ }
+
+ return $this->getTranslationMessage("$key.$subKey", null, $defaultValue);
+ }
+
+ /**
+ * Get the translation of the current week day name (with context for languages with multiple forms).
+ *
+ * @param string|null $context whole format string
+ * @param string $keySuffix "", "_short" or "_min"
+ * @param string|null $defaultValue default value if translation missing
+ *
+ * @return string
+ */
+ public function getTranslatedDayName($context = null, $keySuffix = '', $defaultValue = null)
+ {
+ return $this->getTranslatedFormByRegExp('weekdays', $keySuffix, $context, $this->dayOfWeek, $defaultValue ?: $this->englishDayOfWeek);
+ }
+
+ /**
+ * Get the translation of the current short week day name (with context for languages with multiple forms).
+ *
+ * @param string|null $context whole format string
+ *
+ * @return string
+ */
+ public function getTranslatedShortDayName($context = null)
+ {
+ return $this->getTranslatedDayName($context, '_short', $this->shortEnglishDayOfWeek);
+ }
+
+ /**
+ * Get the translation of the current abbreviated week day name (with context for languages with multiple forms).
+ *
+ * @param string|null $context whole format string
+ *
+ * @return string
+ */
+ public function getTranslatedMinDayName($context = null)
+ {
+ return $this->getTranslatedDayName($context, '_min', $this->shortEnglishDayOfWeek);
+ }
+
+ /**
+ * Get the translation of the current month day name (with context for languages with multiple forms).
+ *
+ * @param string|null $context whole format string
+ * @param string $keySuffix "" or "_short"
+ * @param string|null $defaultValue default value if translation missing
+ *
+ * @return string
+ */
+ public function getTranslatedMonthName($context = null, $keySuffix = '', $defaultValue = null)
+ {
+ return $this->getTranslatedFormByRegExp('months', $keySuffix, $context, $this->month - 1, $defaultValue ?: $this->englishMonth);
+ }
+
+ /**
+ * Get the translation of the current short month day name (with context for languages with multiple forms).
+ *
+ * @param string|null $context whole format string
+ *
+ * @return string
+ */
+ public function getTranslatedShortMonthName($context = null)
+ {
+ return $this->getTranslatedMonthName($context, '_short', $this->shortEnglishMonth);
+ }
+
+ /**
+ * Get/set the day of year.
+ *
+ * @param int|null $value new value for day of year if using as setter.
+ *
+ * @return static|int
+ */
+ public function dayOfYear($value = null)
+ {
+ $dayOfYear = $this->dayOfYear;
+
+ return $value === null ? $dayOfYear : $this->addDays($value - $dayOfYear);
+ }
+
+ /**
+ * Get/set the weekday from 0 (Sunday) to 6 (Saturday).
+ *
+ * @param int|null $value new value for weekday if using as setter.
+ *
+ * @return static|int
+ */
+ public function weekday($value = null)
+ {
+ $dayOfWeek = ($this->dayOfWeek + 7 - (int) ($this->getTranslationMessage('first_day_of_week') ?? 0)) % 7;
+
+ return $value === null ? $dayOfWeek : $this->addDays($value - $dayOfWeek);
+ }
+
+ /**
+ * Get/set the ISO weekday from 1 (Monday) to 7 (Sunday).
+ *
+ * @param int|null $value new value for weekday if using as setter.
+ *
+ * @return static|int
+ */
+ public function isoWeekday($value = null)
+ {
+ $dayOfWeekIso = $this->dayOfWeekIso;
+
+ return $value === null ? $dayOfWeekIso : $this->addDays($value - $dayOfWeekIso);
+ }
+
+ /**
+ * Set any unit to a new value without overflowing current other unit given.
+ *
+ * @param string $valueUnit unit name to modify
+ * @param int $value new value for the input unit
+ * @param string $overflowUnit unit name to not overflow
+ *
+ * @return static
+ */
+ public function setUnitNoOverflow($valueUnit, $value, $overflowUnit)
+ {
+ try {
+ $original = $this->avoidMutation();
+ /** @var static $date */
+ $date = $this->$valueUnit($value);
+ $end = $original->avoidMutation()->endOf($overflowUnit);
+ $start = $original->avoidMutation()->startOf($overflowUnit);
+ if ($date < $start) {
+ $date = $date->setDateTimeFrom($start);
+ } elseif ($date > $end) {
+ $date = $date->setDateTimeFrom($end);
+ }
+
+ return $date;
+ } catch (BadMethodCallException | ReflectionException $exception) {
+ throw new UnknownUnitException($valueUnit, 0, $exception);
+ }
+ }
+
+ /**
+ * Add any unit to a new value without overflowing current other unit given.
+ *
+ * @param string $valueUnit unit name to modify
+ * @param int $value amount to add to the input unit
+ * @param string $overflowUnit unit name to not overflow
+ *
+ * @return static
+ */
+ public function addUnitNoOverflow($valueUnit, $value, $overflowUnit)
+ {
+ return $this->setUnitNoOverflow($valueUnit, $this->$valueUnit + $value, $overflowUnit);
+ }
+
+ /**
+ * Subtract any unit to a new value without overflowing current other unit given.
+ *
+ * @param string $valueUnit unit name to modify
+ * @param int $value amount to subtract to the input unit
+ * @param string $overflowUnit unit name to not overflow
+ *
+ * @return static
+ */
+ public function subUnitNoOverflow($valueUnit, $value, $overflowUnit)
+ {
+ return $this->setUnitNoOverflow($valueUnit, $this->$valueUnit - $value, $overflowUnit);
+ }
+
+ /**
+ * Returns the minutes offset to UTC if no arguments passed, else set the timezone with given minutes shift passed.
+ *
+ * @param int|null $minuteOffset
+ *
+ * @return int|static
+ */
+ public function utcOffset(int $minuteOffset = null)
+ {
+ if (\func_num_args() < 1) {
+ return $this->offsetMinutes;
+ }
+
+ return $this->setTimezone(CarbonTimeZone::createFromMinuteOffset($minuteOffset));
+ }
+
+ /**
+ * Set the date with gregorian year, month and day numbers.
+ *
+ * @see https://php.net/manual/en/datetime.setdate.php
+ *
+ * @param int $year
+ * @param int $month
+ * @param int $day
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function setDate($year, $month, $day)
+ {
+ return parent::setDate((int) $year, (int) $month, (int) $day);
+ }
+
+ /**
+ * Set a date according to the ISO 8601 standard - using weeks and day offsets rather than specific dates.
+ *
+ * @see https://php.net/manual/en/datetime.setisodate.php
+ *
+ * @param int $year
+ * @param int $week
+ * @param int $day
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function setISODate($year, $week, $day = 1)
+ {
+ return parent::setISODate((int) $year, (int) $week, (int) $day);
+ }
+
+ /**
+ * Set the date and time all together.
+ *
+ * @param int $year
+ * @param int $month
+ * @param int $day
+ * @param int $hour
+ * @param int $minute
+ * @param int $second
+ * @param int $microseconds
+ *
+ * @return static
+ */
+ public function setDateTime($year, $month, $day, $hour, $minute, $second = 0, $microseconds = 0)
+ {
+ return $this->setDate($year, $month, $day)->setTime((int) $hour, (int) $minute, (int) $second, (int) $microseconds);
+ }
+
+ /**
+ * Resets the current time of the DateTime object to a different time.
+ *
+ * @see https://php.net/manual/en/datetime.settime.php
+ *
+ * @param int $hour
+ * @param int $minute
+ * @param int $second
+ * @param int $microseconds
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function setTime($hour, $minute, $second = 0, $microseconds = 0)
+ {
+ return parent::setTime((int) $hour, (int) $minute, (int) $second, (int) $microseconds);
+ }
+
+ /**
+ * Set the instance's timestamp.
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $unixTimestamp
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function setTimestamp($unixTimestamp)
+ {
+ [$timestamp, $microseconds] = self::getIntegerAndDecimalParts($unixTimestamp);
+
+ return parent::setTimestamp((int) $timestamp)->setMicroseconds((int) $microseconds);
+ }
+
+ /**
+ * Set the time by time string.
+ *
+ * @param string $time
+ *
+ * @return static
+ */
+ public function setTimeFromTimeString($time)
+ {
+ if (!str_contains($time, ':')) {
+ $time .= ':0';
+ }
+
+ return $this->modify($time);
+ }
+
+ /**
+ * @alias setTimezone
+ *
+ * @param DateTimeZone|string $value
+ *
+ * @return static
+ */
+ public function timezone($value)
+ {
+ return $this->setTimezone($value);
+ }
+
+ /**
+ * Set the timezone or returns the timezone name if no arguments passed.
+ *
+ * @param DateTimeZone|string $value
+ *
+ * @return static|string
+ */
+ public function tz($value = null)
+ {
+ if (\func_num_args() < 1) {
+ return $this->tzName;
+ }
+
+ return $this->setTimezone($value);
+ }
+
+ /**
+ * Set the instance's timezone from a string or object.
+ *
+ * @param DateTimeZone|string $value
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function setTimezone($value)
+ {
+ return parent::setTimezone(static::safeCreateDateTimeZone($value));
+ }
+
+ /**
+ * Set the instance's timezone from a string or object and add/subtract the offset difference.
+ *
+ * @param DateTimeZone|string $value
+ *
+ * @return static
+ */
+ public function shiftTimezone($value)
+ {
+ $offset = $this->offset;
+ $date = $this->setTimezone($value);
+
+ return $date->addRealMicroseconds(($offset - $date->offset) * static::MICROSECONDS_PER_SECOND);
+ }
+
+ /**
+ * Set the instance's timezone to UTC.
+ *
+ * @return static
+ */
+ public function utc()
+ {
+ return $this->setTimezone('UTC');
+ }
+
+ /**
+ * Set the year, month, and date for this instance to that of the passed instance.
+ *
+ * @param Carbon|DateTimeInterface $date now if null
+ *
+ * @return static
+ */
+ public function setDateFrom($date = null)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return $this->setDate($date->year, $date->month, $date->day);
+ }
+
+ /**
+ * Set the hour, minute, second and microseconds for this instance to that of the passed instance.
+ *
+ * @param Carbon|DateTimeInterface $date now if null
+ *
+ * @return static
+ */
+ public function setTimeFrom($date = null)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return $this->setTime($date->hour, $date->minute, $date->second, $date->microsecond);
+ }
+
+ /**
+ * Set the date and time for this instance to that of the passed instance.
+ *
+ * @param Carbon|DateTimeInterface $date
+ *
+ * @return static
+ */
+ public function setDateTimeFrom($date = null)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return $this->modify($date->rawFormat('Y-m-d H:i:s.u'));
+ }
+
+ /**
+ * Get the days of the week
+ *
+ * @return array
+ */
+ public static function getDays()
+ {
+ return static::$days;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////// WEEK SPECIAL DAYS /////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ private static function getFirstDayOfWeek(): int
+ {
+ return (int) static::getTranslationMessageWith(
+ static::getTranslator(),
+ 'first_day_of_week'
+ );
+ }
+
+ /**
+ * Get the first day of week
+ *
+ * @return int
+ */
+ public static function getWeekStartsAt()
+ {
+ if (static::$weekStartsAt === static::WEEK_DAY_AUTO) {
+ return static::getFirstDayOfWeek();
+ }
+
+ return static::$weekStartsAt;
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the
+ * 'first_day_of_week' locale setting to change the start of week according to current locale
+ * selected and implicitly the end of week.
+ *
+ * Set the first day of week
+ *
+ * @param int|string $day week start day (or 'auto' to get the first day of week from Carbon::getLocale() culture).
+ *
+ * @return void
+ */
+ public static function setWeekStartsAt($day)
+ {
+ static::$weekStartsAt = $day === static::WEEK_DAY_AUTO ? $day : max(0, (7 + $day) % 7);
+ }
+
+ /**
+ * Get the last day of week
+ *
+ * @return int
+ */
+ public static function getWeekEndsAt()
+ {
+ if (static::$weekStartsAt === static::WEEK_DAY_AUTO) {
+ return (int) (static::DAYS_PER_WEEK - 1 + static::getFirstDayOfWeek()) % static::DAYS_PER_WEEK;
+ }
+
+ return static::$weekEndsAt;
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek
+ * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the
+ * start of week according to current locale selected and implicitly the end of week.
+ *
+ * Set the last day of week
+ *
+ * @param int|string $day week end day (or 'auto' to get the day before the first day of week
+ * from Carbon::getLocale() culture).
+ *
+ * @return void
+ */
+ public static function setWeekEndsAt($day)
+ {
+ static::$weekEndsAt = $day === static::WEEK_DAY_AUTO ? $day : max(0, (7 + $day) % 7);
+ }
+
+ /**
+ * Get weekend days
+ *
+ * @return array
+ */
+ public static function getWeekendDays()
+ {
+ return static::$weekendDays;
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather consider week-end is always saturday and sunday, and if you have some custom
+ * week-end days to handle, give to those days an other name and create a macro for them:
+ *
+ * ```
+ * Carbon::macro('isDayOff', function ($date) {
+ * return $date->isSunday() || $date->isMonday();
+ * });
+ * Carbon::macro('isNotDayOff', function ($date) {
+ * return !$date->isDayOff();
+ * });
+ * if ($someDate->isDayOff()) ...
+ * if ($someDate->isNotDayOff()) ...
+ * // Add 5 not-off days
+ * $count = 5;
+ * while ($someDate->isDayOff() || ($count-- > 0)) {
+ * $someDate->addDay();
+ * }
+ * ```
+ *
+ * Set weekend days
+ *
+ * @param array $days
+ *
+ * @return void
+ */
+ public static function setWeekendDays($days)
+ {
+ static::$weekendDays = $days;
+ }
+
+ /**
+ * Determine if a time string will produce a relative date.
+ *
+ * @param string $time
+ *
+ * @return bool true if time match a relative date, false if absolute or invalid time string
+ */
+ public static function hasRelativeKeywords($time)
+ {
+ if (!$time || strtotime($time) === false) {
+ return false;
+ }
+
+ $date1 = new DateTime('2000-01-01T00:00:00Z');
+ $date1->modify($time);
+ $date2 = new DateTime('2001-12-25T00:00:00Z');
+ $date2->modify($time);
+
+ return $date1 != $date2;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////// STRING FORMATTING /////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use UTF-8 language packages on every machine.
+ *
+ * Set if UTF8 will be used for localized date/time.
+ *
+ * @param bool $utf8
+ */
+ public static function setUtf8($utf8)
+ {
+ static::$utf8 = $utf8;
+ }
+
+ /**
+ * Format the instance with the current locale. You can set the current
+ * locale using setlocale() https://php.net/setlocale.
+ *
+ * @param string $format
+ *
+ * @return string
+ */
+ public function formatLocalized($format)
+ {
+ // Check for Windows to find and replace the %e modifier correctly.
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ $format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format); // @codeCoverageIgnore
+ }
+
+ $formatted = strftime($format, strtotime($this->toDateTimeString()));
+
+ return static::$utf8 ? utf8_encode($formatted) : $formatted;
+ }
+
+ /**
+ * Returns list of locale formats for ISO formatting.
+ *
+ * @param string|null $locale current locale used if null
+ *
+ * @return array
+ */
+ public function getIsoFormats($locale = null)
+ {
+ return [
+ 'LT' => $this->getTranslationMessage('formats.LT', $locale, 'h:mm A'),
+ 'LTS' => $this->getTranslationMessage('formats.LTS', $locale, 'h:mm:ss A'),
+ 'L' => $this->getTranslationMessage('formats.L', $locale, 'MM/DD/YYYY'),
+ 'LL' => $this->getTranslationMessage('formats.LL', $locale, 'MMMM D, YYYY'),
+ 'LLL' => $this->getTranslationMessage('formats.LLL', $locale, 'MMMM D, YYYY h:mm A'),
+ 'LLLL' => $this->getTranslationMessage('formats.LLLL', $locale, 'dddd, MMMM D, YYYY h:mm A'),
+ ];
+ }
+
+ /**
+ * Returns list of calendar formats for ISO formatting.
+ *
+ * @param string|null $locale current locale used if null
+ *
+ * @return array
+ */
+ public function getCalendarFormats($locale = null)
+ {
+ return [
+ 'sameDay' => $this->getTranslationMessage('calendar.sameDay', $locale, '[Today at] LT'),
+ 'nextDay' => $this->getTranslationMessage('calendar.nextDay', $locale, '[Tomorrow at] LT'),
+ 'nextWeek' => $this->getTranslationMessage('calendar.nextWeek', $locale, 'dddd [at] LT'),
+ 'lastDay' => $this->getTranslationMessage('calendar.lastDay', $locale, '[Yesterday at] LT'),
+ 'lastWeek' => $this->getTranslationMessage('calendar.lastWeek', $locale, '[Last] dddd [at] LT'),
+ 'sameElse' => $this->getTranslationMessage('calendar.sameElse', $locale, 'L'),
+ ];
+ }
+
+ /**
+ * Returns list of locale units for ISO formatting.
+ *
+ * @return array
+ */
+ public static function getIsoUnits()
+ {
+ static $units = null;
+
+ if ($units === null) {
+ $units = [
+ 'OD' => ['getAltNumber', ['day']],
+ 'OM' => ['getAltNumber', ['month']],
+ 'OY' => ['getAltNumber', ['year']],
+ 'OH' => ['getAltNumber', ['hour']],
+ 'Oh' => ['getAltNumber', ['h']],
+ 'Om' => ['getAltNumber', ['minute']],
+ 'Os' => ['getAltNumber', ['second']],
+ 'D' => 'day',
+ 'DD' => ['rawFormat', ['d']],
+ 'Do' => ['ordinal', ['day', 'D']],
+ 'd' => 'dayOfWeek',
+ 'dd' => function (CarbonInterface $date, $originalFormat = null) {
+ return $date->getTranslatedMinDayName($originalFormat);
+ },
+ 'ddd' => function (CarbonInterface $date, $originalFormat = null) {
+ return $date->getTranslatedShortDayName($originalFormat);
+ },
+ 'dddd' => function (CarbonInterface $date, $originalFormat = null) {
+ return $date->getTranslatedDayName($originalFormat);
+ },
+ 'DDD' => 'dayOfYear',
+ 'DDDD' => ['getPaddedUnit', ['dayOfYear', 3]],
+ 'DDDo' => ['ordinal', ['dayOfYear', 'DDD']],
+ 'e' => ['weekday', []],
+ 'E' => 'dayOfWeekIso',
+ 'H' => ['rawFormat', ['G']],
+ 'HH' => ['rawFormat', ['H']],
+ 'h' => ['rawFormat', ['g']],
+ 'hh' => ['rawFormat', ['h']],
+ 'k' => 'noZeroHour',
+ 'kk' => ['getPaddedUnit', ['noZeroHour']],
+ 'hmm' => ['rawFormat', ['gi']],
+ 'hmmss' => ['rawFormat', ['gis']],
+ 'Hmm' => ['rawFormat', ['Gi']],
+ 'Hmmss' => ['rawFormat', ['Gis']],
+ 'm' => 'minute',
+ 'mm' => ['rawFormat', ['i']],
+ 'a' => 'meridiem',
+ 'A' => 'upperMeridiem',
+ 's' => 'second',
+ 'ss' => ['getPaddedUnit', ['second']],
+ 'S' => function (CarbonInterface $date) {
+ return (string) floor($date->micro / 100000);
+ },
+ 'SS' => function (CarbonInterface $date) {
+ return str_pad((string) floor($date->micro / 10000), 2, '0', STR_PAD_LEFT);
+ },
+ 'SSS' => function (CarbonInterface $date) {
+ return str_pad((string) floor($date->micro / 1000), 3, '0', STR_PAD_LEFT);
+ },
+ 'SSSS' => function (CarbonInterface $date) {
+ return str_pad((string) floor($date->micro / 100), 4, '0', STR_PAD_LEFT);
+ },
+ 'SSSSS' => function (CarbonInterface $date) {
+ return str_pad((string) floor($date->micro / 10), 5, '0', STR_PAD_LEFT);
+ },
+ 'SSSSSS' => ['getPaddedUnit', ['micro', 6]],
+ 'SSSSSSS' => function (CarbonInterface $date) {
+ return str_pad((string) floor($date->micro * 10), 7, '0', STR_PAD_LEFT);
+ },
+ 'SSSSSSSS' => function (CarbonInterface $date) {
+ return str_pad((string) floor($date->micro * 100), 8, '0', STR_PAD_LEFT);
+ },
+ 'SSSSSSSSS' => function (CarbonInterface $date) {
+ return str_pad((string) floor($date->micro * 1000), 9, '0', STR_PAD_LEFT);
+ },
+ 'M' => 'month',
+ 'MM' => ['rawFormat', ['m']],
+ 'MMM' => function (CarbonInterface $date, $originalFormat = null) {
+ $month = $date->getTranslatedShortMonthName($originalFormat);
+ $suffix = $date->getTranslationMessage('mmm_suffix');
+ if ($suffix && $month !== $date->monthName) {
+ $month .= $suffix;
+ }
+
+ return $month;
+ },
+ 'MMMM' => function (CarbonInterface $date, $originalFormat = null) {
+ return $date->getTranslatedMonthName($originalFormat);
+ },
+ 'Mo' => ['ordinal', ['month', 'M']],
+ 'Q' => 'quarter',
+ 'Qo' => ['ordinal', ['quarter', 'M']],
+ 'G' => 'isoWeekYear',
+ 'GG' => ['getPaddedUnit', ['isoWeekYear']],
+ 'GGG' => ['getPaddedUnit', ['isoWeekYear', 3]],
+ 'GGGG' => ['getPaddedUnit', ['isoWeekYear', 4]],
+ 'GGGGG' => ['getPaddedUnit', ['isoWeekYear', 5]],
+ 'g' => 'weekYear',
+ 'gg' => ['getPaddedUnit', ['weekYear']],
+ 'ggg' => ['getPaddedUnit', ['weekYear', 3]],
+ 'gggg' => ['getPaddedUnit', ['weekYear', 4]],
+ 'ggggg' => ['getPaddedUnit', ['weekYear', 5]],
+ 'W' => 'isoWeek',
+ 'WW' => ['getPaddedUnit', ['isoWeek']],
+ 'Wo' => ['ordinal', ['isoWeek', 'W']],
+ 'w' => 'week',
+ 'ww' => ['getPaddedUnit', ['week']],
+ 'wo' => ['ordinal', ['week', 'w']],
+ 'x' => ['valueOf', []],
+ 'X' => 'timestamp',
+ 'Y' => 'year',
+ 'YY' => ['rawFormat', ['y']],
+ 'YYYY' => ['getPaddedUnit', ['year', 4]],
+ 'YYYYY' => ['getPaddedUnit', ['year', 5]],
+ 'YYYYYY' => function (CarbonInterface $date) {
+ return ($date->year < 0 ? '' : '+').$date->getPaddedUnit('year', 6);
+ },
+ 'z' => ['rawFormat', ['T']],
+ 'zz' => 'tzName',
+ 'Z' => ['getOffsetString', []],
+ 'ZZ' => ['getOffsetString', ['']],
+ ];
+ }
+
+ return $units;
+ }
+
+ /**
+ * Returns a unit of the instance padded with 0 by default or any other string if specified.
+ *
+ * @param string $unit Carbon unit name
+ * @param int $length Length of the output (2 by default)
+ * @param string $padString String to use for padding ("0" by default)
+ * @param int $padType Side(s) to pad (STR_PAD_LEFT by default)
+ *
+ * @return string
+ */
+ public function getPaddedUnit($unit, $length = 2, $padString = '0', $padType = STR_PAD_LEFT)
+ {
+ return ($this->$unit < 0 ? '-' : '').str_pad((string) abs($this->$unit), $length, $padString, $padType);
+ }
+
+ /**
+ * Return a property with its ordinal.
+ *
+ * @param string $key
+ * @param string|null $period
+ *
+ * @return string
+ */
+ public function ordinal(string $key, ?string $period = null): string
+ {
+ $number = $this->$key;
+ $result = $this->translate('ordinal', [
+ ':number' => $number,
+ ':period' => (string) $period,
+ ]);
+
+ return (string) ($result === 'ordinal' ? $number : $result);
+ }
+
+ /**
+ * Return the meridiem of the current time in the current locale.
+ *
+ * @param bool $isLower if true, returns lowercase variant if available in the current locale.
+ *
+ * @return string
+ */
+ public function meridiem(bool $isLower = false): string
+ {
+ $hour = $this->hour;
+ $index = $hour < 12 ? 0 : 1;
+
+ if ($isLower) {
+ $key = 'meridiem.'.($index + 2);
+ $result = $this->translate($key);
+
+ if ($result !== $key) {
+ return $result;
+ }
+ }
+
+ $key = "meridiem.$index";
+ $result = $this->translate($key);
+ if ($result === $key) {
+ $result = $this->translate('meridiem', [
+ ':hour' => $this->hour,
+ ':minute' => $this->minute,
+ ':isLower' => $isLower,
+ ]);
+
+ if ($result === 'meridiem') {
+ return $isLower ? $this->latinMeridiem : $this->latinUpperMeridiem;
+ }
+ } elseif ($isLower) {
+ $result = mb_strtolower($result);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns the alternative number for a given date property if available in the current locale.
+ *
+ * @param string $key date property
+ *
+ * @return string
+ */
+ public function getAltNumber(string $key): string
+ {
+ return $this->translateNumber(\strlen($key) > 1 ? $this->$key : $this->rawFormat('h'));
+ }
+
+ /**
+ * Format in the current language using ISO replacement patterns.
+ *
+ * @param string $format
+ * @param string|null $originalFormat provide context if a chunk has been passed alone
+ *
+ * @return string
+ */
+ public function isoFormat(string $format, ?string $originalFormat = null): string
+ {
+ $result = '';
+ $length = mb_strlen($format);
+ $originalFormat = $originalFormat ?: $format;
+ $inEscaped = false;
+ $formats = null;
+ $units = null;
+
+ for ($i = 0; $i < $length; $i++) {
+ $char = mb_substr($format, $i, 1);
+
+ if ($char === '\\') {
+ $result .= mb_substr($format, ++$i, 1);
+
+ continue;
+ }
+
+ if ($char === '[' && !$inEscaped) {
+ $inEscaped = true;
+
+ continue;
+ }
+
+ if ($char === ']' && $inEscaped) {
+ $inEscaped = false;
+
+ continue;
+ }
+
+ if ($inEscaped) {
+ $result .= $char;
+
+ continue;
+ }
+
+ $input = mb_substr($format, $i);
+
+ if (preg_match('/^(LTS|LT|[Ll]{1,4})/', $input, $match)) {
+ if ($formats === null) {
+ $formats = $this->getIsoFormats();
+ }
+
+ $code = $match[0];
+ $sequence = $formats[$code] ?? preg_replace_callback(
+ '/MMMM|MM|DD|dddd/',
+ function ($code) {
+ return mb_substr($code[0], 1);
+ },
+ $formats[strtoupper($code)] ?? ''
+ );
+ $rest = mb_substr($format, $i + mb_strlen($code));
+ $format = mb_substr($format, 0, $i).$sequence.$rest;
+ $length = mb_strlen($format);
+ $input = $sequence.$rest;
+ }
+
+ if (preg_match('/^'.CarbonInterface::ISO_FORMAT_REGEXP.'/', $input, $match)) {
+ $code = $match[0];
+
+ if ($units === null) {
+ $units = static::getIsoUnits();
+ }
+
+ $sequence = $units[$code] ?? '';
+
+ if ($sequence instanceof Closure) {
+ $sequence = $sequence($this, $originalFormat);
+ } elseif (\is_array($sequence)) {
+ try {
+ $sequence = $this->{$sequence[0]}(...$sequence[1]);
+ } catch (ReflectionException | InvalidArgumentException | BadMethodCallException $e) {
+ $sequence = '';
+ }
+ } elseif (\is_string($sequence)) {
+ $sequence = $this->$sequence ?? $code;
+ }
+
+ $format = mb_substr($format, 0, $i).$sequence.mb_substr($format, $i + mb_strlen($code));
+ $i += mb_strlen((string) $sequence) - 1;
+ $length = mb_strlen($format);
+ $char = $sequence;
+ }
+
+ $result .= $char;
+ }
+
+ return $result;
+ }
+
+ /**
+ * List of replacements from date() format to isoFormat().
+ *
+ * @return array
+ */
+ public static function getFormatsToIsoReplacements()
+ {
+ static $replacements = null;
+
+ if ($replacements === null) {
+ $replacements = [
+ 'd' => true,
+ 'D' => 'ddd',
+ 'j' => true,
+ 'l' => 'dddd',
+ 'N' => true,
+ 'S' => function ($date) {
+ $day = $date->rawFormat('j');
+
+ return str_replace((string) $day, '', $date->isoFormat('Do'));
+ },
+ 'w' => true,
+ 'z' => true,
+ 'W' => true,
+ 'F' => 'MMMM',
+ 'm' => true,
+ 'M' => 'MMM',
+ 'n' => true,
+ 't' => true,
+ 'L' => true,
+ 'o' => true,
+ 'Y' => true,
+ 'y' => true,
+ 'a' => 'a',
+ 'A' => 'A',
+ 'B' => true,
+ 'g' => true,
+ 'G' => true,
+ 'h' => true,
+ 'H' => true,
+ 'i' => true,
+ 's' => true,
+ 'u' => true,
+ 'v' => true,
+ 'E' => true,
+ 'I' => true,
+ 'O' => true,
+ 'P' => true,
+ 'Z' => true,
+ 'c' => true,
+ 'r' => true,
+ 'U' => true,
+ ];
+ }
+
+ return $replacements;
+ }
+
+ /**
+ * Format as ->format() do (using date replacements patterns from https://php.net/manual/en/function.date.php)
+ * but translate words whenever possible (months, day names, etc.) using the current locale.
+ *
+ * @param string $format
+ *
+ * @return string
+ */
+ public function translatedFormat(string $format): string
+ {
+ $replacements = static::getFormatsToIsoReplacements();
+ $context = '';
+ $isoFormat = '';
+ $length = mb_strlen($format);
+
+ for ($i = 0; $i < $length; $i++) {
+ $char = mb_substr($format, $i, 1);
+
+ if ($char === '\\') {
+ $replacement = mb_substr($format, $i, 2);
+ $isoFormat .= $replacement;
+ $i++;
+
+ continue;
+ }
+
+ if (!isset($replacements[$char])) {
+ $replacement = preg_match('/^[A-Za-z]$/', $char) ? "\\$char" : $char;
+ $isoFormat .= $replacement;
+ $context .= $replacement;
+
+ continue;
+ }
+
+ $replacement = $replacements[$char];
+
+ if ($replacement === true) {
+ static $contextReplacements = null;
+
+ if ($contextReplacements === null) {
+ $contextReplacements = [
+ 'm' => 'MM',
+ 'd' => 'DD',
+ 't' => 'D',
+ 'j' => 'D',
+ 'N' => 'e',
+ 'w' => 'e',
+ 'n' => 'M',
+ 'o' => 'YYYY',
+ 'Y' => 'YYYY',
+ 'y' => 'YY',
+ 'g' => 'h',
+ 'G' => 'H',
+ 'h' => 'hh',
+ 'H' => 'HH',
+ 'i' => 'mm',
+ 's' => 'ss',
+ ];
+ }
+
+ $isoFormat .= '['.$this->rawFormat($char).']';
+ $context .= $contextReplacements[$char] ?? ' ';
+
+ continue;
+ }
+
+ if ($replacement instanceof Closure) {
+ $replacement = '['.$replacement($this).']';
+ $isoFormat .= $replacement;
+ $context .= $replacement;
+
+ continue;
+ }
+
+ $isoFormat .= $replacement;
+ $context .= $replacement;
+ }
+
+ return $this->isoFormat($isoFormat, $context);
+ }
+
+ /**
+ * Returns the offset hour and minute formatted with +/- and a given separator (":" by default).
+ * For example, if the time zone is 9 hours 30 minutes, you'll get "+09:30", with "@@" as first
+ * argument, "+09@@30", with "" as first argument, "+0930". Negative offset will return something
+ * like "-12:00".
+ *
+ * @param string $separator string to place between hours and minutes (":" by default)
+ *
+ * @return string
+ */
+ public function getOffsetString($separator = ':')
+ {
+ $second = $this->getOffset();
+ $symbol = $second < 0 ? '-' : '+';
+ $minute = abs($second) / static::SECONDS_PER_MINUTE;
+ $hour = str_pad((string) floor($minute / static::MINUTES_PER_HOUR), 2, '0', STR_PAD_LEFT);
+ $minute = str_pad((string) ($minute % static::MINUTES_PER_HOUR), 2, '0', STR_PAD_LEFT);
+
+ return "$symbol$hour$separator$minute";
+ }
+
+ protected static function executeStaticCallable($macro, ...$parameters)
+ {
+ return static::bindMacroContext(null, function () use (&$macro, &$parameters) {
+ if ($macro instanceof Closure) {
+ $boundMacro = @Closure::bind($macro, null, static::class);
+
+ return ($boundMacro ?: $macro)(...$parameters);
+ }
+
+ return $macro(...$parameters);
+ });
+ }
+
+ /**
+ * Dynamically handle calls to the class.
+ *
+ * @param string $method magic method name called
+ * @param array $parameters parameters list
+ *
+ * @throws BadMethodCallException
+ *
+ * @return mixed
+ */
+ public static function __callStatic($method, $parameters)
+ {
+ if (!static::hasMacro($method)) {
+ foreach (static::getGenericMacros() as $callback) {
+ try {
+ return static::executeStaticCallable($callback, $method, ...$parameters);
+ } catch (BadMethodCallException $exception) {
+ continue;
+ }
+ }
+ if (static::isStrictModeEnabled()) {
+ throw new UnknownMethodException(sprintf('%s::%s', static::class, $method));
+ }
+
+ return null;
+ }
+
+ return static::executeStaticCallable(static::$globalMacros[$method], ...$parameters);
+ }
+
+ /**
+ * Set specified unit to new given value.
+ *
+ * @param string $unit year, month, day, hour, minute, second or microsecond
+ * @param int $value new value for given unit
+ *
+ * @return static
+ */
+ public function setUnit($unit, $value = null)
+ {
+ $unit = static::singularUnit($unit);
+ $dateUnits = ['year', 'month', 'day'];
+ if (\in_array($unit, $dateUnits)) {
+ return $this->setDate(...array_map(function ($name) use ($unit, $value) {
+ return (int) ($name === $unit ? $value : $this->$name);
+ }, $dateUnits));
+ }
+
+ $units = ['hour', 'minute', 'second', 'micro'];
+ if ($unit === 'millisecond' || $unit === 'milli') {
+ $value *= 1000;
+ $unit = 'micro';
+ } elseif ($unit === 'microsecond') {
+ $unit = 'micro';
+ }
+
+ return $this->setTime(...array_map(function ($name) use ($unit, $value) {
+ return (int) ($name === $unit ? $value : $this->$name);
+ }, $units));
+ }
+
+ /**
+ * Returns standardized singular of a given singular/plural unit name (in English).
+ *
+ * @param string $unit
+ *
+ * @return string
+ */
+ public static function singularUnit(string $unit): string
+ {
+ $unit = rtrim(mb_strtolower($unit), 's');
+
+ if ($unit === 'centurie') {
+ return 'century';
+ }
+
+ if ($unit === 'millennia') {
+ return 'millennium';
+ }
+
+ return $unit;
+ }
+
+ /**
+ * Returns standardized plural of a given singular/plural unit name (in English).
+ *
+ * @param string $unit
+ *
+ * @return string
+ */
+ public static function pluralUnit(string $unit): string
+ {
+ $unit = rtrim(strtolower($unit), 's');
+
+ if ($unit === 'century') {
+ return 'centuries';
+ }
+
+ if ($unit === 'millennium' || $unit === 'millennia') {
+ return 'millennia';
+ }
+
+ return "${unit}s";
+ }
+
+ protected function executeCallable($macro, ...$parameters)
+ {
+ if ($macro instanceof Closure) {
+ $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class);
+
+ return ($boundMacro ?: $macro)(...$parameters);
+ }
+
+ return $macro(...$parameters);
+ }
+
+ protected function executeCallableWithContext($macro, ...$parameters)
+ {
+ return static::bindMacroContext($this, function () use (&$macro, &$parameters) {
+ return $this->executeCallable($macro, ...$parameters);
+ });
+ }
+
+ protected static function getGenericMacros()
+ {
+ foreach (static::$globalGenericMacros as $list) {
+ foreach ($list as $macro) {
+ yield $macro;
+ }
+ }
+ }
+
+ /**
+ * Dynamically handle calls to the class.
+ *
+ * @param string $method magic method name called
+ * @param array $parameters parameters list
+ *
+ * @throws UnknownMethodException|BadMethodCallException|ReflectionException|Throwable
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ $diffSizes = [
+ // @mode diffForHumans
+ 'short' => true,
+ // @mode diffForHumans
+ 'long' => false,
+ ];
+ $diffSyntaxModes = [
+ // @call diffForHumans
+ 'Absolute' => CarbonInterface::DIFF_ABSOLUTE,
+ // @call diffForHumans
+ 'Relative' => CarbonInterface::DIFF_RELATIVE_AUTO,
+ // @call diffForHumans
+ 'RelativeToNow' => CarbonInterface::DIFF_RELATIVE_TO_NOW,
+ // @call diffForHumans
+ 'RelativeToOther' => CarbonInterface::DIFF_RELATIVE_TO_OTHER,
+ ];
+ $sizePattern = implode('|', array_keys($diffSizes));
+ $syntaxPattern = implode('|', array_keys($diffSyntaxModes));
+
+ if (preg_match("/^(?<size>$sizePattern)(?<syntax>$syntaxPattern)DiffForHumans$/", $method, $match)) {
+ $dates = array_filter($parameters, function ($parameter) {
+ return $parameter instanceof DateTimeInterface;
+ });
+ $other = null;
+
+ if (\count($dates)) {
+ $key = key($dates);
+ $other = current($dates);
+ array_splice($parameters, $key, 1);
+ }
+
+ return $this->diffForHumans($other, $diffSyntaxModes[$match['syntax']], $diffSizes[$match['size']], ...$parameters);
+ }
+
+ $roundedValue = $this->callRoundMethod($method, $parameters);
+
+ if ($roundedValue !== null) {
+ return $roundedValue;
+ }
+
+ $unit = rtrim($method, 's');
+
+ if (str_starts_with($unit, 'is')) {
+ $word = substr($unit, 2);
+
+ if (\in_array($word, static::$days)) {
+ return $this->isDayOfWeek($word);
+ }
+
+ switch ($word) {
+ // @call is Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
+ case 'Utc':
+ case 'UTC':
+ return $this->utc;
+ // @call is Check if the current instance has non-UTC timezone.
+ case 'Local':
+ return $this->local;
+ // @call is Check if the current instance is a valid date.
+ case 'Valid':
+ return $this->year !== 0;
+ // @call is Check if the current instance is in a daylight saving time.
+ case 'DST':
+ return $this->dst;
+ }
+ }
+
+ $action = substr($unit, 0, 3);
+ $overflow = null;
+
+ if ($action === 'set') {
+ $unit = strtolower(substr($unit, 3));
+ }
+
+ if (\in_array($unit, static::$units)) {
+ return $this->setUnit($unit, ...$parameters);
+ }
+
+ if ($action === 'add' || $action === 'sub') {
+ $unit = substr($unit, 3);
+
+ if (str_starts_with($unit, 'Real')) {
+ $unit = static::singularUnit(substr($unit, 4));
+
+ return $this->{"${action}RealUnit"}($unit, ...$parameters);
+ }
+
+ if (preg_match('/^(Month|Quarter|Year|Decade|Century|Centurie|Millennium|Millennia)s?(No|With|Without|WithNo)Overflow$/', $unit, $match)) {
+ $unit = $match[1];
+ $overflow = $match[2] === 'With';
+ }
+
+ $unit = static::singularUnit($unit);
+ }
+
+ if (static::isModifiableUnit($unit)) {
+ return $this->{"${action}Unit"}($unit, $parameters[0] ?? 1, $overflow);
+ }
+
+ $sixFirstLetters = substr($unit, 0, 6);
+ $factor = -1;
+
+ if ($sixFirstLetters === 'isLast') {
+ $sixFirstLetters = 'isNext';
+ $factor = 1;
+ }
+
+ if ($sixFirstLetters === 'isNext') {
+ $lowerUnit = strtolower(substr($unit, 6));
+
+ if (static::isModifiableUnit($lowerUnit)) {
+ return $this->copy()->addUnit($lowerUnit, $factor, false)->isSameUnit($lowerUnit, ...$parameters);
+ }
+ }
+
+ if ($sixFirstLetters === 'isSame') {
+ try {
+ return $this->isSameUnit(strtolower(substr($unit, 6)), ...$parameters);
+ } catch (BadComparisonUnitException $exception) {
+ // Try next
+ }
+ }
+
+ if (str_starts_with($unit, 'isCurrent')) {
+ try {
+ return $this->isCurrentUnit(strtolower(substr($unit, 9)));
+ } catch (BadComparisonUnitException | BadMethodCallException $exception) {
+ // Try next
+ }
+ }
+
+ if (str_ends_with($method, 'Until')) {
+ try {
+ $unit = static::singularUnit(substr($method, 0, -5));
+
+ return $this->range($parameters[0] ?? $this, $parameters[1] ?? 1, $unit);
+ } catch (InvalidArgumentException $exception) {
+ // Try macros
+ }
+ }
+
+ return static::bindMacroContext($this, function () use (&$method, &$parameters) {
+ $macro = $this->getLocalMacro($method);
+
+ if (!$macro) {
+ foreach ([$this->localGenericMacros ?: [], static::getGenericMacros()] as $list) {
+ foreach ($list as $callback) {
+ try {
+ return $this->executeCallable($callback, $method, ...$parameters);
+ } catch (BadMethodCallException $exception) {
+ continue;
+ }
+ }
+ }
+
+ if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
+ throw new UnknownMethodException($method);
+ }
+
+ return null;
+ }
+
+ return $this->executeCallable($macro, ...$parameters);
+ });
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Difference.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Difference.php
new file mode 100644
index 0000000..b1cdd6e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Difference.php
@@ -0,0 +1,1141 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\Carbon;
+use Carbon\CarbonImmutable;
+use Carbon\CarbonInterface;
+use Carbon\CarbonInterval;
+use Carbon\CarbonPeriod;
+use Carbon\Translator;
+use Closure;
+use DateInterval;
+use DateTimeInterface;
+use ReturnTypeWillChange;
+
+/**
+ * Trait Difference.
+ *
+ * Depends on the following methods:
+ *
+ * @method bool lessThan($date)
+ * @method static copy()
+ * @method static resolveCarbon($date = null)
+ * @method static Translator translator()
+ */
+trait Difference
+{
+ /**
+ * @codeCoverageIgnore
+ *
+ * @param CarbonInterval $diff
+ */
+ protected static function fixNegativeMicroseconds(CarbonInterval $diff)
+ {
+ if ($diff->s !== 0 || $diff->i !== 0 || $diff->h !== 0 || $diff->d !== 0 || $diff->m !== 0 || $diff->y !== 0) {
+ $diff->f = (round($diff->f * 1000000) + 1000000) / 1000000;
+ $diff->s--;
+
+ if ($diff->s < 0) {
+ $diff->s += 60;
+ $diff->i--;
+
+ if ($diff->i < 0) {
+ $diff->i += 60;
+ $diff->h--;
+
+ if ($diff->h < 0) {
+ $diff->h += 24;
+ $diff->d--;
+
+ if ($diff->d < 0) {
+ $diff->d += 30;
+ $diff->m--;
+
+ if ($diff->m < 0) {
+ $diff->m += 12;
+ $diff->y--;
+ }
+ }
+ }
+ }
+ }
+
+ return;
+ }
+
+ $diff->f *= -1;
+ $diff->invert();
+ }
+
+ /**
+ * @param DateInterval $diff
+ * @param bool $absolute
+ *
+ * @return CarbonInterval
+ */
+ protected static function fixDiffInterval(DateInterval $diff, $absolute)
+ {
+ $diff = CarbonInterval::instance($diff);
+
+ // Work-around for https://bugs.php.net/bug.php?id=77145
+ // @codeCoverageIgnoreStart
+ if ($diff->f > 0 && $diff->y === -1 && $diff->m === 11 && $diff->d >= 27 && $diff->h === 23 && $diff->i === 59 && $diff->s === 59) {
+ $diff->y = 0;
+ $diff->m = 0;
+ $diff->d = 0;
+ $diff->h = 0;
+ $diff->i = 0;
+ $diff->s = 0;
+ $diff->f = (1000000 - round($diff->f * 1000000)) / 1000000;
+ $diff->invert();
+ } elseif ($diff->f < 0) {
+ static::fixNegativeMicroseconds($diff);
+ }
+ // @codeCoverageIgnoreEnd
+
+ if ($absolute && $diff->invert) {
+ $diff->invert();
+ }
+
+ return $diff;
+ }
+
+ /**
+ * Get the difference as a DateInterval instance.
+ * Return relative interval (negative if
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return DateInterval
+ */
+ #[ReturnTypeWillChange]
+ public function diff($date = null, $absolute = false)
+ {
+ $other = $this->resolveCarbon($date);
+
+ // Can be removed if https://github.com/derickr/timelib/pull/110
+ // is merged
+ // @codeCoverageIgnoreStart
+ if (version_compare(PHP_VERSION, '8.1.0-dev', '>=') && $other->tz !== $this->tz) {
+ $other = $other->avoidMutation()->tz($this->tz);
+ }
+ // @codeCoverageIgnoreEnd
+
+ return parent::diff($other, (bool) $absolute);
+ }
+
+ /**
+ * Get the difference as a CarbonInterval instance.
+ * Return absolute interval (always positive) unless you pass false to the second argument.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return CarbonInterval
+ */
+ public function diffAsCarbonInterval($date = null, $absolute = true)
+ {
+ return static::fixDiffInterval($this->diff($this->resolveCarbon($date), $absolute), $absolute);
+ }
+
+ /**
+ * Get the difference in years
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInYears($date = null, $absolute = true)
+ {
+ return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%y');
+ }
+
+ /**
+ * Get the difference in quarters rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInQuarters($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInMonths($date, $absolute) / static::MONTHS_PER_QUARTER);
+ }
+
+ /**
+ * Get the difference in months rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMonths($date = null, $absolute = true)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return $this->diffInYears($date, $absolute) * static::MONTHS_PER_YEAR + (int) $this->diff($date, $absolute)->format('%r%m');
+ }
+
+ /**
+ * Get the difference in weeks rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInWeeks($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInDays($date, $absolute) / static::DAYS_PER_WEEK);
+ }
+
+ /**
+ * Get the difference in days rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInDays($date = null, $absolute = true)
+ {
+ return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%a');
+ }
+
+ /**
+ * Get the difference in days using a filter closure rounded down.
+ *
+ * @param Closure $callback
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInDaysFiltered(Closure $callback, $date = null, $absolute = true)
+ {
+ return $this->diffFiltered(CarbonInterval::day(), $callback, $date, $absolute);
+ }
+
+ /**
+ * Get the difference in hours using a filter closure rounded down.
+ *
+ * @param Closure $callback
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInHoursFiltered(Closure $callback, $date = null, $absolute = true)
+ {
+ return $this->diffFiltered(CarbonInterval::hour(), $callback, $date, $absolute);
+ }
+
+ /**
+ * Get the difference by the given interval using a filter closure.
+ *
+ * @param CarbonInterval $ci An interval to traverse by
+ * @param Closure $callback
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, $absolute = true)
+ {
+ $start = $this;
+ $end = $this->resolveCarbon($date);
+ $inverse = false;
+
+ if ($end < $start) {
+ $start = $end;
+ $end = $this;
+ $inverse = true;
+ }
+
+ $options = CarbonPeriod::EXCLUDE_END_DATE | ($this->isMutable() ? 0 : CarbonPeriod::IMMUTABLE);
+ $diff = $ci->toPeriod($start, $end, $options)->filter($callback)->count();
+
+ return $inverse && !$absolute ? -$diff : $diff;
+ }
+
+ /**
+ * Get the difference in weekdays rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInWeekdays($date = null, $absolute = true)
+ {
+ return $this->diffInDaysFiltered(function (CarbonInterface $date) {
+ return $date->isWeekday();
+ }, $date, $absolute);
+ }
+
+ /**
+ * Get the difference in weekend days using a filter rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInWeekendDays($date = null, $absolute = true)
+ {
+ return $this->diffInDaysFiltered(function (CarbonInterface $date) {
+ return $date->isWeekend();
+ }, $date, $absolute);
+ }
+
+ /**
+ * Get the difference in hours rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInHours($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
+ }
+
+ /**
+ * Get the difference in hours rounded down using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealHours($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
+ }
+
+ /**
+ * Get the difference in minutes rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMinutes($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE);
+ }
+
+ /**
+ * Get the difference in minutes rounded down using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealMinutes($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE);
+ }
+
+ /**
+ * Get the difference in seconds rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInSeconds($date = null, $absolute = true)
+ {
+ $diff = $this->diff($date);
+
+ if ($diff->days === 0) {
+ $diff = static::fixDiffInterval($diff, $absolute);
+ }
+
+ $value = (((($diff->m || $diff->y ? $diff->days : $diff->d) * static::HOURS_PER_DAY) +
+ $diff->h) * static::MINUTES_PER_HOUR +
+ $diff->i) * static::SECONDS_PER_MINUTE +
+ $diff->s;
+
+ return $absolute || !$diff->invert ? $value : -$value;
+ }
+
+ /**
+ * Get the difference in microseconds.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMicroseconds($date = null, $absolute = true)
+ {
+ $diff = $this->diff($date);
+ $value = (int) round(((((($diff->m || $diff->y ? $diff->days : $diff->d) * static::HOURS_PER_DAY) +
+ $diff->h) * static::MINUTES_PER_HOUR +
+ $diff->i) * static::SECONDS_PER_MINUTE +
+ ($diff->f + $diff->s)) * static::MICROSECONDS_PER_SECOND);
+
+ return $absolute || !$diff->invert ? $value : -$value;
+ }
+
+ /**
+ * Get the difference in milliseconds rounded down.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMilliseconds($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND);
+ }
+
+ /**
+ * Get the difference in seconds using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealSeconds($date = null, $absolute = true)
+ {
+ /** @var CarbonInterface $date */
+ $date = $this->resolveCarbon($date);
+ $value = $date->getTimestamp() - $this->getTimestamp();
+
+ return $absolute ? abs($value) : $value;
+ }
+
+ /**
+ * Get the difference in microseconds using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealMicroseconds($date = null, $absolute = true)
+ {
+ /** @var CarbonInterface $date */
+ $date = $this->resolveCarbon($date);
+ $value = ($date->timestamp - $this->timestamp) * static::MICROSECONDS_PER_SECOND +
+ $date->micro - $this->micro;
+
+ return $absolute ? abs($value) : $value;
+ }
+
+ /**
+ * Get the difference in milliseconds rounded down using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealMilliseconds($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInRealMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND);
+ }
+
+ /**
+ * Get the difference in seconds as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInSeconds($date = null, $absolute = true)
+ {
+ return $this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_SECOND;
+ }
+
+ /**
+ * Get the difference in minutes as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInMinutes($date = null, $absolute = true)
+ {
+ return $this->floatDiffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE;
+ }
+
+ /**
+ * Get the difference in hours as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInHours($date = null, $absolute = true)
+ {
+ return $this->floatDiffInMinutes($date, $absolute) / static::MINUTES_PER_HOUR;
+ }
+
+ /**
+ * Get the difference in days as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInDays($date = null, $absolute = true)
+ {
+ $hoursDiff = $this->floatDiffInHours($date, $absolute);
+ $interval = $this->diff($date, $absolute);
+
+ if ($interval->y === 0 && $interval->m === 0 && $interval->d === 0) {
+ return $hoursDiff / static::HOURS_PER_DAY;
+ }
+
+ $daysDiff = (int) $interval->format('%r%a');
+
+ return $daysDiff + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
+ }
+
+ /**
+ * Get the difference in weeks as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInWeeks($date = null, $absolute = true)
+ {
+ return $this->floatDiffInDays($date, $absolute) / static::DAYS_PER_WEEK;
+ }
+
+ /**
+ * Get the difference in months as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInMonths($date = null, $absolute = true)
+ {
+ $start = $this;
+ $end = $this->resolveCarbon($date);
+ $ascending = ($start <= $end);
+ $sign = $absolute || $ascending ? 1 : -1;
+ if (!$ascending) {
+ [$start, $end] = [$end, $start];
+ }
+ $monthsDiff = $start->diffInMonths($end);
+ /** @var Carbon|CarbonImmutable $floorEnd */
+ $floorEnd = $start->avoidMutation()->addMonths($monthsDiff);
+
+ if ($floorEnd >= $end) {
+ return $sign * $monthsDiff;
+ }
+
+ /** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
+ $startOfMonthAfterFloorEnd = $floorEnd->avoidMutation()->addMonth()->startOfMonth();
+
+ if ($startOfMonthAfterFloorEnd > $end) {
+ return $sign * ($monthsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInMonth);
+ }
+
+ return $sign * ($monthsDiff + $floorEnd->floatDiffInDays($startOfMonthAfterFloorEnd) / $floorEnd->daysInMonth + $startOfMonthAfterFloorEnd->floatDiffInDays($end) / $end->daysInMonth);
+ }
+
+ /**
+ * Get the difference in year as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInYears($date = null, $absolute = true)
+ {
+ $start = $this;
+ $end = $this->resolveCarbon($date);
+ $ascending = ($start <= $end);
+ $sign = $absolute || $ascending ? 1 : -1;
+ if (!$ascending) {
+ [$start, $end] = [$end, $start];
+ }
+ $yearsDiff = $start->diffInYears($end);
+ /** @var Carbon|CarbonImmutable $floorEnd */
+ $floorEnd = $start->avoidMutation()->addYears($yearsDiff);
+
+ if ($floorEnd >= $end) {
+ return $sign * $yearsDiff;
+ }
+
+ /** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */
+ $startOfYearAfterFloorEnd = $floorEnd->avoidMutation()->addYear()->startOfYear();
+
+ if ($startOfYearAfterFloorEnd > $end) {
+ return $sign * ($yearsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInYear);
+ }
+
+ return $sign * ($yearsDiff + $floorEnd->floatDiffInDays($startOfYearAfterFloorEnd) / $floorEnd->daysInYear + $startOfYearAfterFloorEnd->floatDiffInDays($end) / $end->daysInYear);
+ }
+
+ /**
+ * Get the difference in seconds as float (microsecond-precision) using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealSeconds($date = null, $absolute = true)
+ {
+ return $this->diffInRealMicroseconds($date, $absolute) / static::MICROSECONDS_PER_SECOND;
+ }
+
+ /**
+ * Get the difference in minutes as float (microsecond-precision) using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealMinutes($date = null, $absolute = true)
+ {
+ return $this->floatDiffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE;
+ }
+
+ /**
+ * Get the difference in hours as float (microsecond-precision) using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealHours($date = null, $absolute = true)
+ {
+ return $this->floatDiffInRealMinutes($date, $absolute) / static::MINUTES_PER_HOUR;
+ }
+
+ /**
+ * Get the difference in days as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealDays($date = null, $absolute = true)
+ {
+ $date = $this->resolveUTC($date);
+ $utc = $this->avoidMutation()->utc();
+ $hoursDiff = $utc->floatDiffInRealHours($date, $absolute);
+
+ return ($hoursDiff < 0 ? -1 : 1) * $utc->diffInDays($date) + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
+ }
+
+ /**
+ * Get the difference in weeks as float (microsecond-precision).
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealWeeks($date = null, $absolute = true)
+ {
+ return $this->floatDiffInRealDays($date, $absolute) / static::DAYS_PER_WEEK;
+ }
+
+ /**
+ * Get the difference in months as float (microsecond-precision) using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealMonths($date = null, $absolute = true)
+ {
+ $start = $this;
+ $end = $this->resolveCarbon($date);
+ $ascending = ($start <= $end);
+ $sign = $absolute || $ascending ? 1 : -1;
+ if (!$ascending) {
+ [$start, $end] = [$end, $start];
+ }
+ $monthsDiff = $start->diffInMonths($end);
+ /** @var Carbon|CarbonImmutable $floorEnd */
+ $floorEnd = $start->avoidMutation()->addMonths($monthsDiff);
+
+ if ($floorEnd >= $end) {
+ return $sign * $monthsDiff;
+ }
+
+ /** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
+ $startOfMonthAfterFloorEnd = $floorEnd->avoidMutation()->addMonth()->startOfMonth();
+
+ if ($startOfMonthAfterFloorEnd > $end) {
+ return $sign * ($monthsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInMonth);
+ }
+
+ return $sign * ($monthsDiff + $floorEnd->floatDiffInRealDays($startOfMonthAfterFloorEnd) / $floorEnd->daysInMonth + $startOfMonthAfterFloorEnd->floatDiffInRealDays($end) / $end->daysInMonth);
+ }
+
+ /**
+ * Get the difference in year as float (microsecond-precision) using timestamps.
+ *
+ * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return float
+ */
+ public function floatDiffInRealYears($date = null, $absolute = true)
+ {
+ $start = $this;
+ $end = $this->resolveCarbon($date);
+ $ascending = ($start <= $end);
+ $sign = $absolute || $ascending ? 1 : -1;
+ if (!$ascending) {
+ [$start, $end] = [$end, $start];
+ }
+ $yearsDiff = $start->diffInYears($end);
+ /** @var Carbon|CarbonImmutable $floorEnd */
+ $floorEnd = $start->avoidMutation()->addYears($yearsDiff);
+
+ if ($floorEnd >= $end) {
+ return $sign * $yearsDiff;
+ }
+
+ /** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */
+ $startOfYearAfterFloorEnd = $floorEnd->avoidMutation()->addYear()->startOfYear();
+
+ if ($startOfYearAfterFloorEnd > $end) {
+ return $sign * ($yearsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInYear);
+ }
+
+ return $sign * ($yearsDiff + $floorEnd->floatDiffInRealDays($startOfYearAfterFloorEnd) / $floorEnd->daysInYear + $startOfYearAfterFloorEnd->floatDiffInRealDays($end) / $end->daysInYear);
+ }
+
+ /**
+ * The number of seconds since midnight.
+ *
+ * @return int
+ */
+ public function secondsSinceMidnight()
+ {
+ return $this->diffInSeconds($this->avoidMutation()->startOfDay());
+ }
+
+ /**
+ * The number of seconds until 23:59:59.
+ *
+ * @return int
+ */
+ public function secondsUntilEndOfDay()
+ {
+ return $this->diffInSeconds($this->avoidMutation()->endOfDay());
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale from current instance to an other
+ * instance given (or now if null given).
+ *
+ * @example
+ * ```
+ * echo Carbon::tomorrow()->diffForHumans() . "\n";
+ * echo Carbon::tomorrow()->diffForHumans(['parts' => 2]) . "\n";
+ * echo Carbon::tomorrow()->diffForHumans(['parts' => 3, 'join' => true]) . "\n";
+ * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday()) . "\n";
+ * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday(), ['short' => true]) . "\n";
+ * ```
+ *
+ * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
+ * if null passed, now will be used as comparison reference;
+ * if any other type, it will be converted to date and used as reference.
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * - 'other' entry (see above)
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single unit)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function diffForHumans($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
+ {
+ /* @var CarbonInterface $this */
+ if (\is_array($other)) {
+ $other['syntax'] = \array_key_exists('syntax', $other) ? $other['syntax'] : $syntax;
+ $syntax = $other;
+ $other = $syntax['other'] ?? null;
+ }
+
+ $intSyntax = &$syntax;
+ if (\is_array($syntax)) {
+ $syntax['syntax'] = $syntax['syntax'] ?? null;
+ $intSyntax = &$syntax['syntax'];
+ }
+ $intSyntax = (int) ($intSyntax === null ? static::DIFF_RELATIVE_AUTO : $intSyntax);
+ $intSyntax = $intSyntax === static::DIFF_RELATIVE_AUTO && $other === null ? static::DIFF_RELATIVE_TO_NOW : $intSyntax;
+
+ $parts = min(7, max(1, (int) $parts));
+
+ return $this->diffAsCarbonInterval($other, false)
+ ->setLocalTranslator($this->getLocalTranslator())
+ ->forHumans($syntax, (bool) $short, $parts, $options ?? $this->localHumanDiffOptions ?? static::getHumanDiffOptions());
+ }
+
+ /**
+ * @alias diffForHumans
+ *
+ * Get the difference in a human readable format in the current locale from current instance to an other
+ * instance given (or now if null given).
+ *
+ * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
+ * if null passed, now will be used as comparison reference;
+ * if any other type, it will be converted to date and used as reference.
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * - 'other' entry (see above)
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single unit)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function from($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
+ {
+ return $this->diffForHumans($other, $syntax, $short, $parts, $options);
+ }
+
+ /**
+ * @alias diffForHumans
+ *
+ * Get the difference in a human readable format in the current locale from current instance to an other
+ * instance given (or now if null given).
+ */
+ public function since($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
+ {
+ return $this->diffForHumans($other, $syntax, $short, $parts, $options);
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given (or now if null given) to current instance.
+ *
+ * When comparing a value in the past to default now:
+ * 1 hour from now
+ * 5 months from now
+ *
+ * When comparing a value in the future to default now:
+ * 1 hour ago
+ * 5 months ago
+ *
+ * When comparing a value in the past to another value:
+ * 1 hour after
+ * 5 months after
+ *
+ * When comparing a value in the future to another value:
+ * 1 hour before
+ * 5 months before
+ *
+ * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
+ * if null passed, now will be used as comparison reference;
+ * if any other type, it will be converted to date and used as reference.
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * - 'other' entry (see above)
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single unit)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function to($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
+ {
+ if (!$syntax && !$other) {
+ $syntax = CarbonInterface::DIFF_RELATIVE_TO_NOW;
+ }
+
+ return $this->resolveCarbon($other)->diffForHumans($this, $syntax, $short, $parts, $options);
+ }
+
+ /**
+ * @alias to
+ *
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given (or now if null given) to current instance.
+ *
+ * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below;
+ * if null passed, now will be used as comparison reference;
+ * if any other type, it will be converted to date and used as reference.
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * - 'other' entry (see above)
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single unit)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function until($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
+ {
+ return $this->to($other, $syntax, $short, $parts, $options);
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale from current
+ * instance to now.
+ *
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single unit)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function fromNow($syntax = null, $short = false, $parts = 1, $options = null)
+ {
+ $other = null;
+
+ if ($syntax instanceof DateTimeInterface) {
+ [$other, $syntax, $short, $parts, $options] = array_pad(\func_get_args(), 5, null);
+ }
+
+ return $this->from($other, $syntax, $short, $parts, $options);
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given to now
+ *
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single part)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function toNow($syntax = null, $short = false, $parts = 1, $options = null)
+ {
+ return $this->to(null, $syntax, $short, $parts, $options);
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given to now
+ *
+ * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
+ * - 'syntax' entry (see below)
+ * - 'short' entry (see below)
+ * - 'parts' entry (see below)
+ * - 'options' entry (see below)
+ * - 'join' entry determines how to join multiple parts of the string
+ * ` - if $join is a string, it's used as a joiner glue
+ * ` - if $join is a callable/closure, it get the list of string and should return a string
+ * ` - if $join is an array, the first item will be the default glue, and the second item
+ * ` will be used instead of the glue for the last item
+ * ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
+ * ` - if $join is missing, a space will be used as glue
+ * if int passed, it add modifiers:
+ * Possible values:
+ * - CarbonInterface::DIFF_ABSOLUTE no modifiers
+ * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
+ * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
+ * Default value: CarbonInterface::DIFF_ABSOLUTE
+ * @param bool $short displays short format of time units
+ * @param int $parts maximum number of parts to display (default value: 1: single part)
+ * @param int $options human diff options
+ *
+ * @return string
+ */
+ public function ago($syntax = null, $short = false, $parts = 1, $options = null)
+ {
+ $other = null;
+
+ if ($syntax instanceof DateTimeInterface) {
+ [$other, $syntax, $short, $parts, $options] = array_pad(\func_get_args(), 5, null);
+ }
+
+ return $this->from($other, $syntax, $short, $parts, $options);
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale from current instance to an other
+ * instance given (or now if null given).
+ *
+ * @return string
+ */
+ public function timespan($other = null, $timezone = null)
+ {
+ if (!$other instanceof DateTimeInterface) {
+ $other = static::parse($other, $timezone);
+ }
+
+ return $this->diffForHumans($other, [
+ 'join' => ', ',
+ 'syntax' => CarbonInterface::DIFF_ABSOLUTE,
+ 'options' => CarbonInterface::NO_ZERO_DIFF,
+ 'parts' => -1,
+ ]);
+ }
+
+ /**
+ * Returns either day of week + time (e.g. "Last Friday at 3:30 PM") if reference time is within 7 days,
+ * or a calendar date (e.g. "10/29/2017") otherwise.
+ *
+ * Language, date and time formats will change according to the current locale.
+ *
+ * @param Carbon|\DateTimeInterface|string|null $referenceTime
+ * @param array $formats
+ *
+ * @return string
+ */
+ public function calendar($referenceTime = null, array $formats = [])
+ {
+ /** @var CarbonInterface $current */
+ $current = $this->avoidMutation()->startOfDay();
+ /** @var CarbonInterface $other */
+ $other = $this->resolveCarbon($referenceTime)->avoidMutation()->setTimezone($this->getTimezone())->startOfDay();
+ $diff = $other->diffInDays($current, false);
+ $format = $diff < -6 ? 'sameElse' : (
+ $diff < -1 ? 'lastWeek' : (
+ $diff < 0 ? 'lastDay' : (
+ $diff < 1 ? 'sameDay' : (
+ $diff < 2 ? 'nextDay' : (
+ $diff < 7 ? 'nextWeek' : 'sameElse'
+ )
+ )
+ )
+ )
+ );
+ $format = array_merge($this->getCalendarFormats(), $formats)[$format];
+ if ($format instanceof Closure) {
+ $format = $format($current, $other) ?? '';
+ }
+
+ return $this->isoFormat((string) $format);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/IntervalRounding.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/IntervalRounding.php
new file mode 100644
index 0000000..6f6c9d1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/IntervalRounding.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\CarbonInterval;
+use Carbon\Exceptions\InvalidIntervalException;
+use DateInterval;
+
+/**
+ * Trait to call rounding methods to interval or the interval of a period.
+ */
+trait IntervalRounding
+{
+ protected function callRoundMethod(string $method, array $parameters)
+ {
+ $action = substr($method, 0, 4);
+
+ if ($action !== 'ceil') {
+ $action = substr($method, 0, 5);
+ }
+
+ if (\in_array($action, ['round', 'floor', 'ceil'])) {
+ return $this->{$action.'Unit'}(substr($method, \strlen($action)), ...$parameters);
+ }
+
+ return null;
+ }
+
+ protected function roundWith($precision, $function)
+ {
+ $unit = 'second';
+
+ if ($precision instanceof DateInterval) {
+ $precision = (string) CarbonInterval::instance($precision);
+ }
+
+ if (\is_string($precision) && preg_match('/^\s*(?<precision>\d+)?\s*(?<unit>\w+)(?<other>\W.*)?$/', $precision, $match)) {
+ if (trim($match['other'] ?? '') !== '') {
+ throw new InvalidIntervalException('Rounding is only possible with single unit intervals.');
+ }
+
+ $precision = (int) ($match['precision'] ?: 1);
+ $unit = $match['unit'];
+ }
+
+ return $this->roundUnit($unit, $precision, $function);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/IntervalStep.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/IntervalStep.php
new file mode 100644
index 0000000..4882eef
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/IntervalStep.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\Carbon;
+use Carbon\CarbonImmutable;
+use Carbon\CarbonInterface;
+use Closure;
+use DateTimeImmutable;
+use DateTimeInterface;
+
+trait IntervalStep
+{
+ /**
+ * Step to apply instead of a fixed interval to get the new date.
+ *
+ * @var Closure|null
+ */
+ protected $step;
+
+ /**
+ * Get the dynamic step in use.
+ *
+ * @return Closure
+ */
+ public function getStep(): ?Closure
+ {
+ return $this->step;
+ }
+
+ /**
+ * Set a step to apply instead of a fixed interval to get the new date.
+ *
+ * Or pass null to switch to fixed interval.
+ *
+ * @param Closure|null $step
+ */
+ public function setStep(?Closure $step): void
+ {
+ $this->step = $step;
+ }
+
+ /**
+ * Take a date and apply either the step if set, or the current interval else.
+ *
+ * The interval/step is applied negatively (typically subtraction instead of addition) if $negated is true.
+ *
+ * @param DateTimeInterface $dateTime
+ * @param bool $negated
+ *
+ * @return CarbonInterface
+ */
+ public function convertDate(DateTimeInterface $dateTime, bool $negated = false): CarbonInterface
+ {
+ /** @var CarbonInterface $carbonDate */
+ $carbonDate = $dateTime instanceof CarbonInterface ? $dateTime : $this->resolveCarbon($dateTime);
+
+ if ($this->step) {
+ return $carbonDate->setDateTimeFrom(($this->step)($carbonDate->avoidMutation(), $negated));
+ }
+
+ if ($negated) {
+ return $carbonDate->rawSub($this);
+ }
+
+ return $carbonDate->rawAdd($this);
+ }
+
+ /**
+ * Convert DateTimeImmutable instance to CarbonImmutable instance and DateTime instance to Carbon instance.
+ *
+ * @param DateTimeInterface $dateTime
+ *
+ * @return Carbon|CarbonImmutable
+ */
+ private function resolveCarbon(DateTimeInterface $dateTime)
+ {
+ if ($dateTime instanceof DateTimeImmutable) {
+ return CarbonImmutable::instance($dateTime);
+ }
+
+ return Carbon::instance($dateTime);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Localization.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Localization.php
new file mode 100644
index 0000000..9162dc9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Localization.php
@@ -0,0 +1,808 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\CarbonInterface;
+use Carbon\Exceptions\InvalidTypeException;
+use Carbon\Exceptions\NotLocaleAwareException;
+use Carbon\Language;
+use Carbon\Translator;
+use Closure;
+use Symfony\Component\Translation\TranslatorBagInterface;
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Contracts\Translation\LocaleAwareInterface;
+use Symfony\Contracts\Translation\TranslatorInterface as ContractsTranslatorInterface;
+
+if (!interface_exists('Symfony\\Component\\Translation\\TranslatorInterface')) {
+ class_alias(
+ 'Symfony\\Contracts\\Translation\\TranslatorInterface',
+ 'Symfony\\Component\\Translation\\TranslatorInterface'
+ );
+}
+
+/**
+ * Trait Localization.
+ *
+ * Embed default and locale translators and translation base methods.
+ */
+trait Localization
+{
+ /**
+ * Default translator.
+ *
+ * @var \Symfony\Component\Translation\TranslatorInterface
+ */
+ protected static $translator;
+
+ /**
+ * Specific translator of the current instance.
+ *
+ * @var \Symfony\Component\Translation\TranslatorInterface
+ */
+ protected $localTranslator;
+
+ /**
+ * Options for diffForHumans().
+ *
+ * @var int
+ */
+ protected static $humanDiffOptions = CarbonInterface::NO_ZERO_DIFF;
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @see settings
+ *
+ * @param int $humanDiffOptions
+ */
+ public static function setHumanDiffOptions($humanDiffOptions)
+ {
+ static::$humanDiffOptions = $humanDiffOptions;
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @see settings
+ *
+ * @param int $humanDiffOption
+ */
+ public static function enableHumanDiffOption($humanDiffOption)
+ {
+ static::$humanDiffOptions = static::getHumanDiffOptions() | $humanDiffOption;
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @see settings
+ *
+ * @param int $humanDiffOption
+ */
+ public static function disableHumanDiffOption($humanDiffOption)
+ {
+ static::$humanDiffOptions = static::getHumanDiffOptions() & ~$humanDiffOption;
+ }
+
+ /**
+ * Return default humanDiff() options (merged flags as integer).
+ *
+ * @return int
+ */
+ public static function getHumanDiffOptions()
+ {
+ return static::$humanDiffOptions;
+ }
+
+ /**
+ * Get the default translator instance in use.
+ *
+ * @return \Symfony\Component\Translation\TranslatorInterface
+ */
+ public static function getTranslator()
+ {
+ return static::translator();
+ }
+
+ /**
+ * Set the default translator instance to use.
+ *
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator
+ *
+ * @return void
+ */
+ public static function setTranslator(TranslatorInterface $translator)
+ {
+ static::$translator = $translator;
+ }
+
+ /**
+ * Return true if the current instance has its own translator.
+ *
+ * @return bool
+ */
+ public function hasLocalTranslator()
+ {
+ return isset($this->localTranslator);
+ }
+
+ /**
+ * Get the translator of the current instance or the default if none set.
+ *
+ * @return \Symfony\Component\Translation\TranslatorInterface
+ */
+ public function getLocalTranslator()
+ {
+ return $this->localTranslator ?: static::translator();
+ }
+
+ /**
+ * Set the translator for the current instance.
+ *
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator
+ *
+ * @return $this
+ */
+ public function setLocalTranslator(TranslatorInterface $translator)
+ {
+ $this->localTranslator = $translator;
+
+ return $this;
+ }
+
+ /**
+ * Returns raw translation message for a given key.
+ *
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator the translator to use
+ * @param string $key key to find
+ * @param string|null $locale current locale used if null
+ * @param string|null $default default value if translation returns the key
+ *
+ * @return string
+ */
+ public static function getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null)
+ {
+ if (!($translator instanceof TranslatorBagInterface && $translator instanceof TranslatorInterface)) {
+ throw new InvalidTypeException(
+ 'Translator does not implement '.TranslatorInterface::class.' and '.TranslatorBagInterface::class.'. '.
+ (\is_object($translator) ? \get_class($translator) : \gettype($translator)).' has been given.'
+ );
+ }
+
+ if (!$locale && $translator instanceof LocaleAwareInterface) {
+ $locale = $translator->getLocale();
+ }
+
+ $result = $translator->getCatalogue($locale)->get($key);
+
+ return $result === $key ? $default : $result;
+ }
+
+ /**
+ * Returns raw translation message for a given key.
+ *
+ * @param string $key key to find
+ * @param string|null $locale current locale used if null
+ * @param string|null $default default value if translation returns the key
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator an optional translator to use
+ *
+ * @return string
+ */
+ public function getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
+ {
+ return static::getTranslationMessageWith($translator ?: $this->getLocalTranslator(), $key, $locale, $default);
+ }
+
+ /**
+ * Translate using translation string or callback available.
+ *
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator
+ * @param string $key
+ * @param array $parameters
+ * @param null $number
+ *
+ * @return string
+ */
+ public static function translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string
+ {
+ $message = static::getTranslationMessageWith($translator, $key, null, $key);
+ if ($message instanceof Closure) {
+ return (string) $message(...array_values($parameters));
+ }
+
+ if ($number !== null) {
+ $parameters['%count%'] = $number;
+ }
+ if (isset($parameters['%count%'])) {
+ $parameters[':count'] = $parameters['%count%'];
+ }
+
+ // @codeCoverageIgnoreStart
+ $choice = $translator instanceof ContractsTranslatorInterface
+ ? $translator->trans($key, $parameters)
+ : $translator->transChoice($key, $number, $parameters);
+ // @codeCoverageIgnoreEnd
+
+ return (string) $choice;
+ }
+
+ /**
+ * Translate using translation string or callback available.
+ *
+ * @param string $key
+ * @param array $parameters
+ * @param string|int|float|null $number
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator
+ *
+ * @return string
+ */
+ public function translate(string $key, array $parameters = [], $number = null, ?TranslatorInterface $translator = null, bool $altNumbers = false): string
+ {
+ $translation = static::translateWith($translator ?: $this->getLocalTranslator(), $key, $parameters, $number);
+
+ if ($number !== null && $altNumbers) {
+ return str_replace($number, $this->translateNumber($number), $translation);
+ }
+
+ return $translation;
+ }
+
+ /**
+ * Returns the alternative number for a given integer if available in the current locale.
+ *
+ * @param int $number
+ *
+ * @return string
+ */
+ public function translateNumber(int $number): string
+ {
+ $translateKey = "alt_numbers.$number";
+ $symbol = $this->translate($translateKey);
+
+ if ($symbol !== $translateKey) {
+ return $symbol;
+ }
+
+ if ($number > 99 && $this->translate('alt_numbers.99') !== 'alt_numbers.99') {
+ $start = '';
+ foreach ([10000, 1000, 100] as $exp) {
+ $key = "alt_numbers_pow.$exp";
+ if ($number >= $exp && $number < $exp * 10 && ($pow = $this->translate($key)) !== $key) {
+ $unit = floor($number / $exp);
+ $number -= $unit * $exp;
+ $start .= ($unit > 1 ? $this->translate("alt_numbers.$unit") : '').$pow;
+ }
+ }
+ $result = '';
+ while ($number) {
+ $chunk = $number % 100;
+ $result = $this->translate("alt_numbers.$chunk").$result;
+ $number = floor($number / 100);
+ }
+
+ return "$start$result";
+ }
+
+ if ($number > 9 && $this->translate('alt_numbers.9') !== 'alt_numbers.9') {
+ $result = '';
+ while ($number) {
+ $chunk = $number % 10;
+ $result = $this->translate("alt_numbers.$chunk").$result;
+ $number = floor($number / 10);
+ }
+
+ return $result;
+ }
+
+ return (string) $number;
+ }
+
+ /**
+ * Translate a time string from a locale to an other.
+ *
+ * @param string $timeString date/time/duration string to translate (may also contain English)
+ * @param string|null $from input locale of the $timeString parameter (`Carbon::getLocale()` by default)
+ * @param string|null $to output locale of the result returned (`"en"` by default)
+ * @param int $mode specify what to translate with options:
+ * - CarbonInterface::TRANSLATE_ALL (default)
+ * - CarbonInterface::TRANSLATE_MONTHS
+ * - CarbonInterface::TRANSLATE_DAYS
+ * - CarbonInterface::TRANSLATE_UNITS
+ * - CarbonInterface::TRANSLATE_MERIDIEM
+ * You can use pipe to group: CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS
+ *
+ * @return string
+ */
+ public static function translateTimeString($timeString, $from = null, $to = null, $mode = CarbonInterface::TRANSLATE_ALL)
+ {
+ // Fallback source and destination locales
+ $from = $from ?: static::getLocale();
+ $to = $to ?: 'en';
+
+ if ($from === $to) {
+ return $timeString;
+ }
+
+ // Standardize apostrophe
+ $timeString = strtr($timeString, ['’' => "'"]);
+
+ $fromTranslations = [];
+ $toTranslations = [];
+
+ foreach (['from', 'to'] as $key) {
+ $language = $$key;
+ $translator = Translator::get($language);
+ $translations = $translator->getMessages();
+
+ if (!isset($translations[$language])) {
+ return $timeString;
+ }
+
+ $translationKey = $key.'Translations';
+ $messages = $translations[$language];
+ $months = $messages['months'] ?? [];
+ $weekdays = $messages['weekdays'] ?? [];
+ $meridiem = $messages['meridiem'] ?? ['AM', 'PM'];
+
+ if ($key === 'from') {
+ foreach (['months', 'weekdays'] as $variable) {
+ $list = $messages[$variable.'_standalone'] ?? null;
+
+ if ($list) {
+ foreach ($$variable as $index => &$name) {
+ $name .= '|'.$messages[$variable.'_standalone'][$index];
+ }
+ }
+ }
+ }
+
+ $$translationKey = array_merge(
+ $mode & CarbonInterface::TRANSLATE_MONTHS ? static::getTranslationArray($months, 12, $timeString) : [],
+ $mode & CarbonInterface::TRANSLATE_MONTHS ? static::getTranslationArray($messages['months_short'] ?? [], 12, $timeString) : [],
+ $mode & CarbonInterface::TRANSLATE_DAYS ? static::getTranslationArray($weekdays, 7, $timeString) : [],
+ $mode & CarbonInterface::TRANSLATE_DAYS ? static::getTranslationArray($messages['weekdays_short'] ?? [], 7, $timeString) : [],
+ $mode & CarbonInterface::TRANSLATE_DIFF ? static::translateWordsByKeys([
+ 'diff_now',
+ 'diff_today',
+ 'diff_yesterday',
+ 'diff_tomorrow',
+ 'diff_before_yesterday',
+ 'diff_after_tomorrow',
+ ], $messages, $key) : [],
+ $mode & CarbonInterface::TRANSLATE_UNITS ? static::translateWordsByKeys([
+ 'year',
+ 'month',
+ 'week',
+ 'day',
+ 'hour',
+ 'minute',
+ 'second',
+ ], $messages, $key) : [],
+ $mode & CarbonInterface::TRANSLATE_MERIDIEM ? array_map(function ($hour) use ($meridiem) {
+ if (\is_array($meridiem)) {
+ return $meridiem[$hour < 12 ? 0 : 1];
+ }
+
+ return $meridiem($hour, 0, false);
+ }, range(0, 23)) : []
+ );
+ }
+
+ return substr(preg_replace_callback('/(?<=[\d\s+.\/,_-])('.implode('|', $fromTranslations).')(?=[\d\s+.\/,_-])/iu', function ($match) use ($fromTranslations, $toTranslations) {
+ [$chunk] = $match;
+
+ foreach ($fromTranslations as $index => $word) {
+ if (preg_match("/^$word\$/iu", $chunk)) {
+ return $toTranslations[$index] ?? '';
+ }
+ }
+
+ return $chunk; // @codeCoverageIgnore
+ }, " $timeString "), 1, -1);
+ }
+
+ /**
+ * Translate a time string from the current locale (`$date->locale()`) to an other.
+ *
+ * @param string $timeString time string to translate
+ * @param string|null $to output locale of the result returned ("en" by default)
+ *
+ * @return string
+ */
+ public function translateTimeStringTo($timeString, $to = null)
+ {
+ return static::translateTimeString($timeString, $this->getTranslatorLocale(), $to);
+ }
+
+ /**
+ * Get/set the locale for the current instance.
+ *
+ * @param string|null $locale
+ * @param string ...$fallbackLocales
+ *
+ * @return $this|string
+ */
+ public function locale(string $locale = null, ...$fallbackLocales)
+ {
+ if ($locale === null) {
+ return $this->getTranslatorLocale();
+ }
+
+ if (!$this->localTranslator || $this->getTranslatorLocale($this->localTranslator) !== $locale) {
+ $translator = Translator::get($locale);
+
+ if (!empty($fallbackLocales)) {
+ $translator->setFallbackLocales($fallbackLocales);
+
+ foreach ($fallbackLocales as $fallbackLocale) {
+ $messages = Translator::get($fallbackLocale)->getMessages();
+
+ if (isset($messages[$fallbackLocale])) {
+ $translator->setMessages($fallbackLocale, $messages[$fallbackLocale]);
+ }
+ }
+ }
+
+ $this->setLocalTranslator($translator);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the current translator locale.
+ *
+ * @return string
+ */
+ public static function getLocale()
+ {
+ return static::getLocaleAwareTranslator()->getLocale();
+ }
+
+ /**
+ * Set the current translator locale and indicate if the source locale file exists.
+ * Pass 'auto' as locale to use closest language from the current LC_TIME locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function setLocale($locale)
+ {
+ return static::getLocaleAwareTranslator()->setLocale($locale) !== false;
+ }
+
+ /**
+ * Set the fallback locale.
+ *
+ * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
+ *
+ * @param string $locale
+ */
+ public static function setFallbackLocale($locale)
+ {
+ $translator = static::getTranslator();
+
+ if (method_exists($translator, 'setFallbackLocales')) {
+ $translator->setFallbackLocales([$locale]);
+
+ if ($translator instanceof Translator) {
+ $preferredLocale = $translator->getLocale();
+ $translator->setMessages($preferredLocale, array_replace_recursive(
+ $translator->getMessages()[$locale] ?? [],
+ Translator::get($locale)->getMessages()[$locale] ?? [],
+ $translator->getMessages($preferredLocale)
+ ));
+ }
+ }
+ }
+
+ /**
+ * Get the fallback locale.
+ *
+ * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
+ *
+ * @return string|null
+ */
+ public static function getFallbackLocale()
+ {
+ $translator = static::getTranslator();
+
+ if (method_exists($translator, 'getFallbackLocales')) {
+ return $translator->getFallbackLocales()[0] ?? null;
+ }
+
+ return null;
+ }
+
+ /**
+ * Set the current locale to the given, execute the passed function, reset the locale to previous one,
+ * then return the result of the closure (or null if the closure was void).
+ *
+ * @param string $locale locale ex. en
+ * @param callable $func
+ *
+ * @return mixed
+ */
+ public static function executeWithLocale($locale, $func)
+ {
+ $currentLocale = static::getLocale();
+ $result = $func(static::setLocale($locale) ? static::getLocale() : false, static::translator());
+ static::setLocale($currentLocale);
+
+ return $result;
+ }
+
+ /**
+ * Returns true if the given locale is internally supported and has short-units support.
+ * Support is considered enabled if either year, day or hour has a short variant translated.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasShortUnits($locale)
+ {
+ return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
+ return $newLocale &&
+ (
+ ($y = static::translateWith($translator, 'y')) !== 'y' &&
+ $y !== static::translateWith($translator, 'year')
+ ) || (
+ ($y = static::translateWith($translator, 'd')) !== 'd' &&
+ $y !== static::translateWith($translator, 'day')
+ ) || (
+ ($y = static::translateWith($translator, 'h')) !== 'h' &&
+ $y !== static::translateWith($translator, 'hour')
+ );
+ });
+ }
+
+ /**
+ * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
+ * Support is considered enabled if the 4 sentences are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasDiffSyntax($locale)
+ {
+ return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
+ if (!$newLocale) {
+ return false;
+ }
+
+ foreach (['ago', 'from_now', 'before', 'after'] as $key) {
+ if ($translator instanceof TranslatorBagInterface && $translator->getCatalogue($newLocale)->get($key) instanceof Closure) {
+ continue;
+ }
+
+ if ($translator->trans($key) === $key) {
+ return false;
+ }
+ }
+
+ return true;
+ });
+ }
+
+ /**
+ * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
+ * Support is considered enabled if the 3 words are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasDiffOneDayWords($locale)
+ {
+ return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
+ return $newLocale &&
+ $translator->trans('diff_now') !== 'diff_now' &&
+ $translator->trans('diff_yesterday') !== 'diff_yesterday' &&
+ $translator->trans('diff_tomorrow') !== 'diff_tomorrow';
+ });
+ }
+
+ /**
+ * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
+ * Support is considered enabled if the 2 words are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasDiffTwoDayWords($locale)
+ {
+ return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
+ return $newLocale &&
+ $translator->trans('diff_before_yesterday') !== 'diff_before_yesterday' &&
+ $translator->trans('diff_after_tomorrow') !== 'diff_after_tomorrow';
+ });
+ }
+
+ /**
+ * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
+ * Support is considered enabled if the 4 sentences are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasPeriodSyntax($locale)
+ {
+ return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
+ return $newLocale &&
+ $translator->trans('period_recurrences') !== 'period_recurrences' &&
+ $translator->trans('period_interval') !== 'period_interval' &&
+ $translator->trans('period_start_date') !== 'period_start_date' &&
+ $translator->trans('period_end_date') !== 'period_end_date';
+ });
+ }
+
+ /**
+ * Returns the list of internally available locales and already loaded custom locales.
+ * (It will ignore custom translator dynamic loading.)
+ *
+ * @return array
+ */
+ public static function getAvailableLocales()
+ {
+ $translator = static::getLocaleAwareTranslator();
+
+ return $translator instanceof Translator
+ ? $translator->getAvailableLocales()
+ : [$translator->getLocale()];
+ }
+
+ /**
+ * Returns list of Language object for each available locale. This object allow you to get the ISO name, native
+ * name, region and variant of the locale.
+ *
+ * @return Language[]
+ */
+ public static function getAvailableLocalesInfo()
+ {
+ $languages = [];
+ foreach (static::getAvailableLocales() as $id) {
+ $languages[$id] = new Language($id);
+ }
+
+ return $languages;
+ }
+
+ /**
+ * Initialize the default translator instance if necessary.
+ *
+ * @return \Symfony\Component\Translation\TranslatorInterface
+ */
+ protected static function translator()
+ {
+ if (static::$translator === null) {
+ static::$translator = Translator::get();
+ }
+
+ return static::$translator;
+ }
+
+ /**
+ * Get the locale of a given translator.
+ *
+ * If null or omitted, current local translator is used.
+ * If no local translator is in use, current global translator is used.
+ *
+ * @param null $translator
+ *
+ * @return string|null
+ */
+ protected function getTranslatorLocale($translator = null): ?string
+ {
+ if (\func_num_args() === 0) {
+ $translator = $this->getLocalTranslator();
+ }
+
+ $translator = static::getLocaleAwareTranslator($translator);
+
+ return $translator ? $translator->getLocale() : null;
+ }
+
+ /**
+ * Throw an error if passed object is not LocaleAwareInterface.
+ *
+ * @param LocaleAwareInterface|null $translator
+ *
+ * @return LocaleAwareInterface|null
+ */
+ protected static function getLocaleAwareTranslator($translator = null)
+ {
+ if (\func_num_args() === 0) {
+ $translator = static::translator();
+ }
+
+ if ($translator && !($translator instanceof LocaleAwareInterface || method_exists($translator, 'getLocale'))) {
+ throw new NotLocaleAwareException($translator);
+ }
+
+ return $translator;
+ }
+
+ /**
+ * Return the word cleaned from its translation codes.
+ *
+ * @param string $word
+ *
+ * @return string
+ */
+ private static function cleanWordFromTranslationString($word)
+ {
+ $word = str_replace([':count', '%count', ':time'], '', $word);
+ $word = strtr($word, ['’' => "'"]);
+ $word = preg_replace('/({\d+(,(\d+|Inf))?}|[\[\]]\d+(,(\d+|Inf))?[\[\]])/', '', $word);
+
+ return trim($word);
+ }
+
+ /**
+ * Translate a list of words.
+ *
+ * @param string[] $keys keys to translate.
+ * @param string[] $messages messages bag handling translations.
+ * @param string $key 'to' (to get the translation) or 'from' (to get the detection RegExp pattern).
+ *
+ * @return string[]
+ */
+ private static function translateWordsByKeys($keys, $messages, $key): array
+ {
+ return array_map(function ($wordKey) use ($messages, $key) {
+ $message = $key === 'from' && isset($messages[$wordKey.'_regexp'])
+ ? $messages[$wordKey.'_regexp']
+ : ($messages[$wordKey] ?? null);
+
+ if (!$message) {
+ return '>>DO NOT REPLACE<<';
+ }
+
+ $parts = explode('|', $message);
+
+ return $key === 'to'
+ ? static::cleanWordFromTranslationString(end($parts))
+ : '(?:'.implode('|', array_map([static::class, 'cleanWordFromTranslationString'], $parts)).')';
+ }, $keys);
+ }
+
+ /**
+ * Get an array of translations based on the current date.
+ *
+ * @param callable $translation
+ * @param int $length
+ * @param string $timeString
+ *
+ * @return string[]
+ */
+ private static function getTranslationArray($translation, $length, $timeString): array
+ {
+ $filler = '>>DO NOT REPLACE<<';
+
+ if (\is_array($translation)) {
+ return array_pad($translation, $length, $filler);
+ }
+
+ $list = [];
+ $date = static::now();
+
+ for ($i = 0; $i < $length; $i++) {
+ $list[] = $translation($date, $timeString, $i) ?? $filler;
+ }
+
+ return $list;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Macro.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Macro.php
new file mode 100644
index 0000000..d413526
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Macro.php
@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+/**
+ * Trait Macros.
+ *
+ * Allows users to register macros within the Carbon class.
+ */
+trait Macro
+{
+ use Mixin;
+
+ /**
+ * The registered macros.
+ *
+ * @var array
+ */
+ protected static $globalMacros = [];
+
+ /**
+ * The registered generic macros.
+ *
+ * @var array
+ */
+ protected static $globalGenericMacros = [];
+
+ /**
+ * Register a custom macro.
+ *
+ * @example
+ * ```
+ * $userSettings = [
+ * 'locale' => 'pt',
+ * 'timezone' => 'America/Sao_Paulo',
+ * ];
+ * Carbon::macro('userFormat', function () use ($userSettings) {
+ * return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar();
+ * });
+ * echo Carbon::yesterday()->hours(11)->userFormat();
+ * ```
+ *
+ * @param string $name
+ * @param object|callable $macro
+ *
+ * @return void
+ */
+ public static function macro($name, $macro)
+ {
+ static::$globalMacros[$name] = $macro;
+ }
+
+ /**
+ * Remove all macros and generic macros.
+ */
+ public static function resetMacros()
+ {
+ static::$globalMacros = [];
+ static::$globalGenericMacros = [];
+ }
+
+ /**
+ * Register a custom macro.
+ *
+ * @param object|callable $macro
+ * @param int $priority marco with higher priority is tried first
+ *
+ * @return void
+ */
+ public static function genericMacro($macro, $priority = 0)
+ {
+ if (!isset(static::$globalGenericMacros[$priority])) {
+ static::$globalGenericMacros[$priority] = [];
+ krsort(static::$globalGenericMacros, SORT_NUMERIC);
+ }
+
+ static::$globalGenericMacros[$priority][] = $macro;
+ }
+
+ /**
+ * Checks if macro is registered globally.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public static function hasMacro($name)
+ {
+ return isset(static::$globalMacros[$name]);
+ }
+
+ /**
+ * Get the raw callable macro registered globally for a given name.
+ *
+ * @param string $name
+ *
+ * @return callable|null
+ */
+ public static function getMacro($name)
+ {
+ return static::$globalMacros[$name] ?? null;
+ }
+
+ /**
+ * Checks if macro is registered globally or locally.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function hasLocalMacro($name)
+ {
+ return ($this->localMacros && isset($this->localMacros[$name])) || static::hasMacro($name);
+ }
+
+ /**
+ * Get the raw callable macro registered globally or locally for a given name.
+ *
+ * @param string $name
+ *
+ * @return callable|null
+ */
+ public function getLocalMacro($name)
+ {
+ return ($this->localMacros ?? [])[$name] ?? static::getMacro($name);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Mixin.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Mixin.php
new file mode 100644
index 0000000..b9c868d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Mixin.php
@@ -0,0 +1,190 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Closure;
+use Generator;
+use ReflectionClass;
+use ReflectionException;
+use ReflectionMethod;
+use Throwable;
+
+/**
+ * Trait Mixin.
+ *
+ * Allows mixing in entire classes with multiple macros.
+ */
+trait Mixin
+{
+ /**
+ * Stack of macro instance contexts.
+ *
+ * @var array
+ */
+ protected static $macroContextStack = [];
+
+ /**
+ * Mix another object into the class.
+ *
+ * @example
+ * ```
+ * Carbon::mixin(new class {
+ * public function addMoon() {
+ * return function () {
+ * return $this->addDays(30);
+ * };
+ * }
+ * public function subMoon() {
+ * return function () {
+ * return $this->subDays(30);
+ * };
+ * }
+ * });
+ * $fullMoon = Carbon::create('2018-12-22');
+ * $nextFullMoon = $fullMoon->addMoon();
+ * $blackMoon = Carbon::create('2019-01-06');
+ * $previousBlackMoon = $blackMoon->subMoon();
+ * echo "$nextFullMoon\n";
+ * echo "$previousBlackMoon\n";
+ * ```
+ *
+ * @param object|string $mixin
+ *
+ * @throws ReflectionException
+ *
+ * @return void
+ */
+ public static function mixin($mixin)
+ {
+ \is_string($mixin) && trait_exists($mixin)
+ ? static::loadMixinTrait($mixin)
+ : static::loadMixinClass($mixin);
+ }
+
+ /**
+ * @param object|string $mixin
+ *
+ * @throws ReflectionException
+ */
+ private static function loadMixinClass($mixin)
+ {
+ $methods = (new ReflectionClass($mixin))->getMethods(
+ ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
+ );
+
+ foreach ($methods as $method) {
+ if ($method->isConstructor() || $method->isDestructor()) {
+ continue;
+ }
+
+ $method->setAccessible(true);
+
+ static::macro($method->name, $method->invoke($mixin));
+ }
+ }
+
+ /**
+ * @param string $trait
+ */
+ private static function loadMixinTrait($trait)
+ {
+ $context = eval(self::getAnonymousClassCodeForTrait($trait));
+ $className = \get_class($context);
+
+ foreach (self::getMixableMethods($context) as $name) {
+ $closureBase = Closure::fromCallable([$context, $name]);
+
+ static::macro($name, function () use ($closureBase, $className) {
+ /** @phpstan-ignore-next-line */
+ $context = isset($this) ? $this->cast($className) : new $className();
+
+ try {
+ // @ is required to handle error if not converted into exceptions
+ $closure = @$closureBase->bindTo($context);
+ } catch (Throwable $throwable) { // @codeCoverageIgnore
+ $closure = $closureBase; // @codeCoverageIgnore
+ }
+
+ // in case of errors not converted into exceptions
+ $closure = $closure ?? $closureBase;
+
+ return $closure(...\func_get_args());
+ });
+ }
+ }
+
+ private static function getAnonymousClassCodeForTrait(string $trait)
+ {
+ return 'return new class() extends '.static::class.' {use '.$trait.';};';
+ }
+
+ private static function getMixableMethods(self $context): Generator
+ {
+ foreach (get_class_methods($context) as $name) {
+ if (method_exists(static::class, $name)) {
+ continue;
+ }
+
+ yield $name;
+ }
+ }
+
+ /**
+ * Stack a Carbon context from inside calls of self::this() and execute a given action.
+ *
+ * @param static|null $context
+ * @param callable $callable
+ *
+ * @throws Throwable
+ *
+ * @return mixed
+ */
+ protected static function bindMacroContext($context, callable $callable)
+ {
+ static::$macroContextStack[] = $context;
+ $exception = null;
+ $result = null;
+
+ try {
+ $result = $callable();
+ } catch (Throwable $throwable) {
+ $exception = $throwable;
+ }
+
+ array_pop(static::$macroContextStack);
+
+ if ($exception) {
+ throw $exception;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Return the current context from inside a macro callee or a null if static.
+ *
+ * @return static|null
+ */
+ protected static function context()
+ {
+ return end(static::$macroContextStack) ?: null;
+ }
+
+ /**
+ * Return the current context from inside a macro callee or a new one if static.
+ *
+ * @return static
+ */
+ protected static function this()
+ {
+ return end(static::$macroContextStack) ?: new static();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Modifiers.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Modifiers.php
new file mode 100644
index 0000000..2fd6426
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Modifiers.php
@@ -0,0 +1,469 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\CarbonInterface;
+use ReturnTypeWillChange;
+
+/**
+ * Trait Modifiers.
+ *
+ * Returns dates relative to current date using modifier short-hand.
+ */
+trait Modifiers
+{
+ /**
+ * Midday/noon hour.
+ *
+ * @var int
+ */
+ protected static $midDayAt = 12;
+
+ /**
+ * get midday/noon hour
+ *
+ * @return int
+ */
+ public static function getMidDayAt()
+ {
+ return static::$midDayAt;
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather consider mid-day is always 12pm, then if you need to test if it's an other
+ * hour, test it explicitly:
+ * $date->format('G') == 13
+ * or to set explicitly to a given hour:
+ * $date->setTime(13, 0, 0, 0)
+ *
+ * Set midday/noon hour
+ *
+ * @param int $hour midday hour
+ *
+ * @return void
+ */
+ public static function setMidDayAt($hour)
+ {
+ static::$midDayAt = $hour;
+ }
+
+ /**
+ * Modify to midday, default to self::$midDayAt
+ *
+ * @return static
+ */
+ public function midDay()
+ {
+ return $this->setTime(static::$midDayAt, 0, 0, 0);
+ }
+
+ /**
+ * Modify to the next occurrence of a given modifier such as a day of
+ * the week. If no modifier is provided, modify to the next occurrence
+ * of the current day of the week. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param string|int|null $modifier
+ *
+ * @return static
+ */
+ public function next($modifier = null)
+ {
+ if ($modifier === null) {
+ $modifier = $this->dayOfWeek;
+ }
+
+ return $this->change(
+ 'next '.(\is_string($modifier) ? $modifier : static::$days[$modifier])
+ );
+ }
+
+ /**
+ * Go forward or backward to the next week- or weekend-day.
+ *
+ * @param bool $weekday
+ * @param bool $forward
+ *
+ * @return static
+ */
+ private function nextOrPreviousDay($weekday = true, $forward = true)
+ {
+ /** @var CarbonInterface $date */
+ $date = $this;
+ $step = $forward ? 1 : -1;
+
+ do {
+ $date = $date->addDays($step);
+ } while ($weekday ? $date->isWeekend() : $date->isWeekday());
+
+ return $date;
+ }
+
+ /**
+ * Go forward to the next weekday.
+ *
+ * @return static
+ */
+ public function nextWeekday()
+ {
+ return $this->nextOrPreviousDay();
+ }
+
+ /**
+ * Go backward to the previous weekday.
+ *
+ * @return static
+ */
+ public function previousWeekday()
+ {
+ return $this->nextOrPreviousDay(true, false);
+ }
+
+ /**
+ * Go forward to the next weekend day.
+ *
+ * @return static
+ */
+ public function nextWeekendDay()
+ {
+ return $this->nextOrPreviousDay(false);
+ }
+
+ /**
+ * Go backward to the previous weekend day.
+ *
+ * @return static
+ */
+ public function previousWeekendDay()
+ {
+ return $this->nextOrPreviousDay(false, false);
+ }
+
+ /**
+ * Modify to the previous occurrence of a given modifier such as a day of
+ * the week. If no dayOfWeek is provided, modify to the previous occurrence
+ * of the current day of the week. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param string|int|null $modifier
+ *
+ * @return static
+ */
+ public function previous($modifier = null)
+ {
+ if ($modifier === null) {
+ $modifier = $this->dayOfWeek;
+ }
+
+ return $this->change(
+ 'last '.(\is_string($modifier) ? $modifier : static::$days[$modifier])
+ );
+ }
+
+ /**
+ * Modify to the first occurrence of a given day of the week
+ * in the current month. If no dayOfWeek is provided, modify to the
+ * first day of the current month. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek
+ *
+ * @return static
+ */
+ public function firstOfMonth($dayOfWeek = null)
+ {
+ $date = $this->startOfDay();
+
+ if ($dayOfWeek === null) {
+ return $date->day(1);
+ }
+
+ return $date->modify('first '.static::$days[$dayOfWeek].' of '.$date->rawFormat('F').' '.$date->year);
+ }
+
+ /**
+ * Modify to the last occurrence of a given day of the week
+ * in the current month. If no dayOfWeek is provided, modify to the
+ * last day of the current month. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek
+ *
+ * @return static
+ */
+ public function lastOfMonth($dayOfWeek = null)
+ {
+ $date = $this->startOfDay();
+
+ if ($dayOfWeek === null) {
+ return $date->day($date->daysInMonth);
+ }
+
+ return $date->modify('last '.static::$days[$dayOfWeek].' of '.$date->rawFormat('F').' '.$date->year);
+ }
+
+ /**
+ * Modify to the given occurrence of a given day of the week
+ * in the current month. If the calculated occurrence is outside the scope
+ * of the current month, then return false and no modifications are made.
+ * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int $nth
+ * @param int $dayOfWeek
+ *
+ * @return mixed
+ */
+ public function nthOfMonth($nth, $dayOfWeek)
+ {
+ $date = $this->avoidMutation()->firstOfMonth();
+ $check = $date->rawFormat('Y-m');
+ $date = $date->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
+
+ return $date->rawFormat('Y-m') === $check ? $this->modify((string) $date) : false;
+ }
+
+ /**
+ * Modify to the first occurrence of a given day of the week
+ * in the current quarter. If no dayOfWeek is provided, modify to the
+ * first day of the current quarter. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function firstOfQuarter($dayOfWeek = null)
+ {
+ return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER - 2, 1)->firstOfMonth($dayOfWeek);
+ }
+
+ /**
+ * Modify to the last occurrence of a given day of the week
+ * in the current quarter. If no dayOfWeek is provided, modify to the
+ * last day of the current quarter. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function lastOfQuarter($dayOfWeek = null)
+ {
+ return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER, 1)->lastOfMonth($dayOfWeek);
+ }
+
+ /**
+ * Modify to the given occurrence of a given day of the week
+ * in the current quarter. If the calculated occurrence is outside the scope
+ * of the current quarter, then return false and no modifications are made.
+ * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int $nth
+ * @param int $dayOfWeek
+ *
+ * @return mixed
+ */
+ public function nthOfQuarter($nth, $dayOfWeek)
+ {
+ $date = $this->avoidMutation()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER);
+ $lastMonth = $date->month;
+ $year = $date->year;
+ $date = $date->firstOfQuarter()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
+
+ return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify((string) $date);
+ }
+
+ /**
+ * Modify to the first occurrence of a given day of the week
+ * in the current year. If no dayOfWeek is provided, modify to the
+ * first day of the current year. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function firstOfYear($dayOfWeek = null)
+ {
+ return $this->month(1)->firstOfMonth($dayOfWeek);
+ }
+
+ /**
+ * Modify to the last occurrence of a given day of the week
+ * in the current year. If no dayOfWeek is provided, modify to the
+ * last day of the current year. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function lastOfYear($dayOfWeek = null)
+ {
+ return $this->month(static::MONTHS_PER_YEAR)->lastOfMonth($dayOfWeek);
+ }
+
+ /**
+ * Modify to the given occurrence of a given day of the week
+ * in the current year. If the calculated occurrence is outside the scope
+ * of the current year, then return false and no modifications are made.
+ * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int $nth
+ * @param int $dayOfWeek
+ *
+ * @return mixed
+ */
+ public function nthOfYear($nth, $dayOfWeek)
+ {
+ $date = $this->avoidMutation()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
+
+ return $this->year === $date->year ? $this->modify((string) $date) : false;
+ }
+
+ /**
+ * Modify the current instance to the average of a given instance (default now) and the current instance
+ * (second-precision).
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date
+ *
+ * @return static
+ */
+ public function average($date = null)
+ {
+ return $this->addRealMicroseconds((int) ($this->diffInRealMicroseconds($this->resolveCarbon($date), false) / 2));
+ }
+
+ /**
+ * Get the closest date from the instance (second-precision).
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ *
+ * @return static
+ */
+ public function closest($date1, $date2)
+ {
+ return $this->diffInRealMicroseconds($date1) < $this->diffInRealMicroseconds($date2) ? $date1 : $date2;
+ }
+
+ /**
+ * Get the farthest date from the instance (second-precision).
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ *
+ * @return static
+ */
+ public function farthest($date1, $date2)
+ {
+ return $this->diffInRealMicroseconds($date1) > $this->diffInRealMicroseconds($date2) ? $date1 : $date2;
+ }
+
+ /**
+ * Get the minimum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return static
+ */
+ public function min($date = null)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return $this->lt($date) ? $this : $date;
+ }
+
+ /**
+ * Get the minimum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see min()
+ *
+ * @return static
+ */
+ public function minimum($date = null)
+ {
+ return $this->min($date);
+ }
+
+ /**
+ * Get the maximum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return static
+ */
+ public function max($date = null)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return $this->gt($date) ? $this : $date;
+ }
+
+ /**
+ * Get the maximum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see max()
+ *
+ * @return static
+ */
+ public function maximum($date = null)
+ {
+ return $this->max($date);
+ }
+
+ /**
+ * Calls \DateTime::modify if mutable or \DateTimeImmutable::modify else.
+ *
+ * @see https://php.net/manual/en/datetime.modify.php
+ */
+ #[ReturnTypeWillChange]
+ public function modify($modify)
+ {
+ return parent::modify((string) $modify);
+ }
+
+ /**
+ * Similar to native modify() method of DateTime but can handle more grammars.
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->change('next 2pm');
+ * ```
+ *
+ * @link https://php.net/manual/en/datetime.modify.php
+ *
+ * @param string $modifier
+ *
+ * @return static
+ */
+ public function change($modifier)
+ {
+ return $this->modify(preg_replace_callback('/^(next|previous|last)\s+(\d{1,2}(h|am|pm|:\d{1,2}(:\d{1,2})?))$/i', function ($match) {
+ $match[2] = str_replace('h', ':00', $match[2]);
+ $test = $this->avoidMutation()->modify($match[2]);
+ $method = $match[1] === 'next' ? 'lt' : 'gt';
+ $match[1] = $test->$method($this) ? $match[1].' day' : 'today';
+
+ return $match[1].' '.$match[2];
+ }, strtr(trim($modifier), [
+ ' at ' => ' ',
+ 'just now' => 'now',
+ 'after tomorrow' => 'tomorrow +1 day',
+ 'before yesterday' => 'yesterday -1 day',
+ ])));
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Mutability.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Mutability.php
new file mode 100644
index 0000000..66eaa12
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Mutability.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\Carbon;
+use Carbon\CarbonImmutable;
+
+/**
+ * Trait Mutability.
+ *
+ * Utils to know if the current object is mutable or immutable and convert it.
+ */
+trait Mutability
+{
+ use Cast;
+
+ /**
+ * Returns true if the current class/instance is mutable.
+ *
+ * @return bool
+ */
+ public static function isMutable()
+ {
+ return false;
+ }
+
+ /**
+ * Returns true if the current class/instance is immutable.
+ *
+ * @return bool
+ */
+ public static function isImmutable()
+ {
+ return !static::isMutable();
+ }
+
+ /**
+ * Return a mutable copy of the instance.
+ *
+ * @return Carbon
+ */
+ public function toMutable()
+ {
+ /** @var Carbon $date */
+ $date = $this->cast(Carbon::class);
+
+ return $date;
+ }
+
+ /**
+ * Return a immutable copy of the instance.
+ *
+ * @return CarbonImmutable
+ */
+ public function toImmutable()
+ {
+ /** @var CarbonImmutable $date */
+ $date = $this->cast(CarbonImmutable::class);
+
+ return $date;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php
new file mode 100644
index 0000000..252df3a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+trait ObjectInitialisation
+{
+ /**
+ * True when parent::__construct has been called.
+ *
+ * @var string
+ */
+ protected $constructedObjectId;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Options.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Options.php
new file mode 100644
index 0000000..0a49372
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Options.php
@@ -0,0 +1,466 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\CarbonInterface;
+use DateTimeInterface;
+use Throwable;
+
+/**
+ * Trait Options.
+ *
+ * Embed base methods to change settings of Carbon classes.
+ *
+ * Depends on the following methods:
+ *
+ * @method \Carbon\Carbon|\Carbon\CarbonImmutable shiftTimezone($timezone) Set the timezone
+ */
+trait Options
+{
+ use Localization;
+
+ /**
+ * Customizable PHP_INT_SIZE override.
+ *
+ * @var int
+ */
+ public static $PHPIntSize = PHP_INT_SIZE;
+
+ /**
+ * First day of week.
+ *
+ * @var int|string
+ */
+ protected static $weekStartsAt = CarbonInterface::MONDAY;
+
+ /**
+ * Last day of week.
+ *
+ * @var int|string
+ */
+ protected static $weekEndsAt = CarbonInterface::SUNDAY;
+
+ /**
+ * Days of weekend.
+ *
+ * @var array
+ */
+ protected static $weekendDays = [
+ CarbonInterface::SATURDAY,
+ CarbonInterface::SUNDAY,
+ ];
+
+ /**
+ * Format regex patterns.
+ *
+ * @var array<string, string>
+ */
+ protected static $regexFormats = [
+ 'd' => '(3[01]|[12][0-9]|0[1-9])',
+ 'D' => '(Sun|Mon|Tue|Wed|Thu|Fri|Sat)',
+ 'j' => '([123][0-9]|[1-9])',
+ 'l' => '([a-zA-Z]{2,})',
+ 'N' => '([1-7])',
+ 'S' => '(st|nd|rd|th)',
+ 'w' => '([0-6])',
+ 'z' => '(36[0-5]|3[0-5][0-9]|[12][0-9]{2}|[1-9]?[0-9])',
+ 'W' => '(5[012]|[1-4][0-9]|0?[1-9])',
+ 'F' => '([a-zA-Z]{2,})',
+ 'm' => '(1[012]|0[1-9])',
+ 'M' => '([a-zA-Z]{3})',
+ 'n' => '(1[012]|[1-9])',
+ 't' => '(2[89]|3[01])',
+ 'L' => '(0|1)',
+ 'o' => '([1-9][0-9]{0,4})',
+ 'Y' => '([1-9]?[0-9]{4})',
+ 'y' => '([0-9]{2})',
+ 'a' => '(am|pm)',
+ 'A' => '(AM|PM)',
+ 'B' => '([0-9]{3})',
+ 'g' => '(1[012]|[1-9])',
+ 'G' => '(2[0-3]|1?[0-9])',
+ 'h' => '(1[012]|0[1-9])',
+ 'H' => '(2[0-3]|[01][0-9])',
+ 'i' => '([0-5][0-9])',
+ 's' => '([0-5][0-9])',
+ 'u' => '([0-9]{1,6})',
+ 'v' => '([0-9]{1,3})',
+ 'e' => '([a-zA-Z]{1,5})|([a-zA-Z]*\\/[a-zA-Z]*)',
+ 'I' => '(0|1)',
+ 'O' => '([+-](1[012]|0[0-9])[0134][05])',
+ 'P' => '([+-](1[012]|0[0-9]):[0134][05])',
+ 'p' => '(Z|[+-](1[012]|0[0-9]):[0134][05])',
+ 'T' => '([a-zA-Z]{1,5})',
+ 'Z' => '(-?[1-5]?[0-9]{1,4})',
+ 'U' => '([0-9]*)',
+
+ // The formats below are combinations of the above formats.
+ 'c' => '(([1-9]?[0-9]{4})-(1[012]|0[1-9])-(3[01]|[12][0-9]|0[1-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])[+-](1[012]|0[0-9]):([0134][05]))', // Y-m-dTH:i:sP
+ 'r' => '(([a-zA-Z]{3}), ([123][0-9]|0[1-9]) ([a-zA-Z]{3}) ([1-9]?[0-9]{4}) (2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]) [+-](1[012]|0[0-9])([0134][05]))', // D, d M Y H:i:s O
+ ];
+
+ /**
+ * Format modifiers (such as available in createFromFormat) regex patterns.
+ *
+ * @var array
+ */
+ protected static $regexFormatModifiers = [
+ '*' => '.+',
+ ' ' => '[ ]',
+ '#' => '[;:\\/.,()-]',
+ '?' => '([^a]|[a])',
+ '!' => '',
+ '|' => '',
+ '+' => '',
+ ];
+
+ /**
+ * Indicates if months should be calculated with overflow.
+ * Global setting.
+ *
+ * @var bool
+ */
+ protected static $monthsOverflow = true;
+
+ /**
+ * Indicates if years should be calculated with overflow.
+ * Global setting.
+ *
+ * @var bool
+ */
+ protected static $yearsOverflow = true;
+
+ /**
+ * Indicates if the strict mode is in use.
+ * Global setting.
+ *
+ * @var bool
+ */
+ protected static $strictModeEnabled = true;
+
+ /**
+ * Function to call instead of format.
+ *
+ * @var string|callable|null
+ */
+ protected static $formatFunction;
+
+ /**
+ * Function to call instead of createFromFormat.
+ *
+ * @var string|callable|null
+ */
+ protected static $createFromFormatFunction;
+
+ /**
+ * Function to call instead of parse.
+ *
+ * @var string|callable|null
+ */
+ protected static $parseFunction;
+
+ /**
+ * Indicates if months should be calculated with overflow.
+ * Specific setting.
+ *
+ * @var bool|null
+ */
+ protected $localMonthsOverflow;
+
+ /**
+ * Indicates if years should be calculated with overflow.
+ * Specific setting.
+ *
+ * @var bool|null
+ */
+ protected $localYearsOverflow;
+
+ /**
+ * Indicates if the strict mode is in use.
+ * Specific setting.
+ *
+ * @var bool|null
+ */
+ protected $localStrictModeEnabled;
+
+ /**
+ * Options for diffForHumans and forHumans methods.
+ *
+ * @var bool|null
+ */
+ protected $localHumanDiffOptions;
+
+ /**
+ * Format to use on string cast.
+ *
+ * @var string|null
+ */
+ protected $localToStringFormat;
+
+ /**
+ * Format to use on JSON serialization.
+ *
+ * @var string|null
+ */
+ protected $localSerializer;
+
+ /**
+ * Instance-specific macros.
+ *
+ * @var array|null
+ */
+ protected $localMacros;
+
+ /**
+ * Instance-specific generic macros.
+ *
+ * @var array|null
+ */
+ protected $localGenericMacros;
+
+ /**
+ * Function to call instead of format.
+ *
+ * @var string|callable|null
+ */
+ protected $localFormatFunction;
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * @see settings
+ *
+ * Enable the strict mode (or disable with passing false).
+ *
+ * @param bool $strictModeEnabled
+ */
+ public static function useStrictMode($strictModeEnabled = true)
+ {
+ static::$strictModeEnabled = $strictModeEnabled;
+ }
+
+ /**
+ * Returns true if the strict mode is globally in use, false else.
+ * (It can be overridden in specific instances.)
+ *
+ * @return bool
+ */
+ public static function isStrictModeEnabled()
+ {
+ return static::$strictModeEnabled;
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @see settings
+ *
+ * Indicates if months should be calculated with overflow.
+ *
+ * @param bool $monthsOverflow
+ *
+ * @return void
+ */
+ public static function useMonthsOverflow($monthsOverflow = true)
+ {
+ static::$monthsOverflow = $monthsOverflow;
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @see settings
+ *
+ * Reset the month overflow behavior.
+ *
+ * @return void
+ */
+ public static function resetMonthsOverflow()
+ {
+ static::$monthsOverflow = true;
+ }
+
+ /**
+ * Get the month overflow global behavior (can be overridden in specific instances).
+ *
+ * @return bool
+ */
+ public static function shouldOverflowMonths()
+ {
+ return static::$monthsOverflow;
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @see settings
+ *
+ * Indicates if years should be calculated with overflow.
+ *
+ * @param bool $yearsOverflow
+ *
+ * @return void
+ */
+ public static function useYearsOverflow($yearsOverflow = true)
+ {
+ static::$yearsOverflow = $yearsOverflow;
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather use the ->settings() method.
+ * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
+ * are available for quarters, years, decade, centuries, millennia (singular and plural forms).
+ * @see settings
+ *
+ * Reset the month overflow behavior.
+ *
+ * @return void
+ */
+ public static function resetYearsOverflow()
+ {
+ static::$yearsOverflow = true;
+ }
+
+ /**
+ * Get the month overflow global behavior (can be overridden in specific instances).
+ *
+ * @return bool
+ */
+ public static function shouldOverflowYears()
+ {
+ return static::$yearsOverflow;
+ }
+
+ /**
+ * Set specific options.
+ * - strictMode: true|false|null
+ * - monthOverflow: true|false|null
+ * - yearOverflow: true|false|null
+ * - humanDiffOptions: int|null
+ * - toStringFormat: string|Closure|null
+ * - toJsonFormat: string|Closure|null
+ * - locale: string|null
+ * - timezone: \DateTimeZone|string|int|null
+ * - macros: array|null
+ * - genericMacros: array|null
+ *
+ * @param array $settings
+ *
+ * @return $this|static
+ */
+ public function settings(array $settings)
+ {
+ $this->localStrictModeEnabled = $settings['strictMode'] ?? null;
+ $this->localMonthsOverflow = $settings['monthOverflow'] ?? null;
+ $this->localYearsOverflow = $settings['yearOverflow'] ?? null;
+ $this->localHumanDiffOptions = $settings['humanDiffOptions'] ?? null;
+ $this->localToStringFormat = $settings['toStringFormat'] ?? null;
+ $this->localSerializer = $settings['toJsonFormat'] ?? null;
+ $this->localMacros = $settings['macros'] ?? null;
+ $this->localGenericMacros = $settings['genericMacros'] ?? null;
+ $this->localFormatFunction = $settings['formatFunction'] ?? null;
+
+ if (isset($settings['locale'])) {
+ $locales = $settings['locale'];
+
+ if (!\is_array($locales)) {
+ $locales = [$locales];
+ }
+
+ $this->locale(...$locales);
+ }
+
+ if (isset($settings['timezone'])) {
+ return $this->shiftTimezone($settings['timezone']);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns current local settings.
+ *
+ * @return array
+ */
+ public function getSettings()
+ {
+ $settings = [];
+ $map = [
+ 'localStrictModeEnabled' => 'strictMode',
+ 'localMonthsOverflow' => 'monthOverflow',
+ 'localYearsOverflow' => 'yearOverflow',
+ 'localHumanDiffOptions' => 'humanDiffOptions',
+ 'localToStringFormat' => 'toStringFormat',
+ 'localSerializer' => 'toJsonFormat',
+ 'localMacros' => 'macros',
+ 'localGenericMacros' => 'genericMacros',
+ 'locale' => 'locale',
+ 'tzName' => 'timezone',
+ 'localFormatFunction' => 'formatFunction',
+ ];
+
+ foreach ($map as $property => $key) {
+ $value = $this->$property ?? null;
+
+ if ($value !== null) {
+ $settings[$key] = $value;
+ }
+ }
+
+ return $settings;
+ }
+
+ /**
+ * Show truthy properties on var_dump().
+ *
+ * @return array
+ */
+ public function __debugInfo()
+ {
+ $infos = array_filter(get_object_vars($this), function ($var) {
+ return $var;
+ });
+
+ foreach (['dumpProperties', 'constructedObjectId'] as $property) {
+ if (isset($infos[$property])) {
+ unset($infos[$property]);
+ }
+ }
+
+ $this->addExtraDebugInfos($infos);
+
+ return $infos;
+ }
+
+ protected function addExtraDebugInfos(&$infos): void
+ {
+ if ($this instanceof DateTimeInterface) {
+ try {
+ if (!isset($infos['date'])) {
+ $infos['date'] = $this->format(CarbonInterface::MOCK_DATETIME_FORMAT);
+ }
+
+ if (!isset($infos['timezone'])) {
+ $infos['timezone'] = $this->tzName;
+ }
+ } catch (Throwable $exception) {
+ // noop
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Rounding.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Rounding.php
new file mode 100644
index 0000000..03d3fe6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Rounding.php
@@ -0,0 +1,238 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\CarbonInterface;
+use Carbon\Exceptions\UnknownUnitException;
+
+/**
+ * Trait Rounding.
+ *
+ * Round, ceil, floor units.
+ *
+ * Depends on the following methods:
+ *
+ * @method static copy()
+ * @method static startOfWeek(int $weekStartsAt = null)
+ */
+trait Rounding
+{
+ use IntervalRounding;
+
+ /**
+ * Round the current instance at the given unit with given precision if specified and the given function.
+ *
+ * @param string $unit
+ * @param float|int $precision
+ * @param string $function
+ *
+ * @return CarbonInterface
+ */
+ public function roundUnit($unit, $precision = 1, $function = 'round')
+ {
+ $metaUnits = [
+ // @call roundUnit
+ 'millennium' => [static::YEARS_PER_MILLENNIUM, 'year'],
+ // @call roundUnit
+ 'century' => [static::YEARS_PER_CENTURY, 'year'],
+ // @call roundUnit
+ 'decade' => [static::YEARS_PER_DECADE, 'year'],
+ // @call roundUnit
+ 'quarter' => [static::MONTHS_PER_QUARTER, 'month'],
+ // @call roundUnit
+ 'millisecond' => [1000, 'microsecond'],
+ ];
+ $normalizedUnit = static::singularUnit($unit);
+ $ranges = array_merge(static::getRangesByUnit(), [
+ // @call roundUnit
+ 'microsecond' => [0, 999999],
+ ]);
+ $factor = 1;
+ $initialMonth = $this->month;
+
+ if ($normalizedUnit === 'week') {
+ $normalizedUnit = 'day';
+ $precision *= static::DAYS_PER_WEEK;
+ }
+
+ if (isset($metaUnits[$normalizedUnit])) {
+ [$factor, $normalizedUnit] = $metaUnits[$normalizedUnit];
+ }
+
+ $precision *= $factor;
+
+ if (!isset($ranges[$normalizedUnit])) {
+ throw new UnknownUnitException($unit);
+ }
+
+ $found = false;
+ $fraction = 0;
+ $arguments = null;
+ $factor = $this->year < 0 ? -1 : 1;
+ $changes = [];
+
+ foreach ($ranges as $unit => [$minimum, $maximum]) {
+ if ($normalizedUnit === $unit) {
+ $arguments = [$this->$unit, $minimum];
+ $fraction = $precision - floor($precision);
+ $found = true;
+
+ continue;
+ }
+
+ if ($found) {
+ $delta = $maximum + 1 - $minimum;
+ $factor /= $delta;
+ $fraction *= $delta;
+ $arguments[0] += $this->$unit * $factor;
+ $changes[$unit] = round(
+ $minimum + ($fraction ? $fraction * $function(($this->$unit - $minimum) / $fraction) : 0)
+ );
+
+ // Cannot use modulo as it lose double precision
+ while ($changes[$unit] >= $delta) {
+ $changes[$unit] -= $delta;
+ }
+
+ $fraction -= floor($fraction);
+ }
+ }
+
+ [$value, $minimum] = $arguments;
+ $normalizedValue = floor($function(($value - $minimum) / $precision) * $precision + $minimum);
+
+ /** @var CarbonInterface $result */
+ $result = $this->$normalizedUnit($normalizedValue);
+
+ foreach ($changes as $unit => $value) {
+ $result = $result->$unit($value);
+ }
+
+ return $normalizedUnit === 'month' && $precision <= 1 && abs($result->month - $initialMonth) === 2
+ // Re-run the change in case an overflow occurred
+ ? $result->$normalizedUnit($normalizedValue)
+ : $result;
+ }
+
+ /**
+ * Truncate the current instance at the given unit with given precision if specified.
+ *
+ * @param string $unit
+ * @param float|int $precision
+ *
+ * @return CarbonInterface
+ */
+ public function floorUnit($unit, $precision = 1)
+ {
+ return $this->roundUnit($unit, $precision, 'floor');
+ }
+
+ /**
+ * Ceil the current instance at the given unit with given precision if specified.
+ *
+ * @param string $unit
+ * @param float|int $precision
+ *
+ * @return CarbonInterface
+ */
+ public function ceilUnit($unit, $precision = 1)
+ {
+ return $this->roundUnit($unit, $precision, 'ceil');
+ }
+
+ /**
+ * Round the current instance second with given precision if specified.
+ *
+ * @param float|int|string|\DateInterval|null $precision
+ * @param string $function
+ *
+ * @return CarbonInterface
+ */
+ public function round($precision = 1, $function = 'round')
+ {
+ return $this->roundWith($precision, $function);
+ }
+
+ /**
+ * Round the current instance second with given precision if specified.
+ *
+ * @param float|int|string|\DateInterval|null $precision
+ *
+ * @return CarbonInterface
+ */
+ public function floor($precision = 1)
+ {
+ return $this->round($precision, 'floor');
+ }
+
+ /**
+ * Ceil the current instance second with given precision if specified.
+ *
+ * @param float|int|string|\DateInterval|null $precision
+ *
+ * @return CarbonInterface
+ */
+ public function ceil($precision = 1)
+ {
+ return $this->round($precision, 'ceil');
+ }
+
+ /**
+ * Round the current instance week.
+ *
+ * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
+ *
+ * @return CarbonInterface
+ */
+ public function roundWeek($weekStartsAt = null)
+ {
+ return $this->closest(
+ $this->avoidMutation()->floorWeek($weekStartsAt),
+ $this->avoidMutation()->ceilWeek($weekStartsAt)
+ );
+ }
+
+ /**
+ * Truncate the current instance week.
+ *
+ * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
+ *
+ * @return CarbonInterface
+ */
+ public function floorWeek($weekStartsAt = null)
+ {
+ return $this->startOfWeek($weekStartsAt);
+ }
+
+ /**
+ * Ceil the current instance week.
+ *
+ * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week
+ *
+ * @return CarbonInterface
+ */
+ public function ceilWeek($weekStartsAt = null)
+ {
+ if ($this->isMutable()) {
+ $startOfWeek = $this->avoidMutation()->startOfWeek($weekStartsAt);
+
+ return $startOfWeek != $this ?
+ $this->startOfWeek($weekStartsAt)->addWeek() :
+ $this;
+ }
+
+ $startOfWeek = $this->startOfWeek($weekStartsAt);
+
+ return $startOfWeek != $this ?
+ $startOfWeek->addWeek() :
+ $this->avoidMutation();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Serialization.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Serialization.php
new file mode 100644
index 0000000..a27e4e3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Serialization.php
@@ -0,0 +1,237 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\Exceptions\InvalidFormatException;
+use ReturnTypeWillChange;
+use Throwable;
+
+/**
+ * Trait Serialization.
+ *
+ * Serialization and JSON stuff.
+ *
+ * Depends on the following properties:
+ *
+ * @property int $year
+ * @property int $month
+ * @property int $daysInMonth
+ * @property int $quarter
+ *
+ * Depends on the following methods:
+ *
+ * @method string|static locale(string $locale = null, string ...$fallbackLocales)
+ * @method string toJSON()
+ */
+trait Serialization
+{
+ use ObjectInitialisation;
+
+ /**
+ * The custom Carbon JSON serializer.
+ *
+ * @var callable|null
+ */
+ protected static $serializer;
+
+ /**
+ * List of key to use for dump/serialization.
+ *
+ * @var string[]
+ */
+ protected $dumpProperties = ['date', 'timezone_type', 'timezone'];
+
+ /**
+ * Locale to dump comes here before serialization.
+ *
+ * @var string|null
+ */
+ protected $dumpLocale;
+
+ /**
+ * Embed date properties to dump in a dedicated variables so it won't overlap native
+ * DateTime ones.
+ *
+ * @var array|null
+ */
+ protected $dumpDateProperties;
+
+ /**
+ * Return a serialized string of the instance.
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ return serialize($this);
+ }
+
+ /**
+ * Create an instance from a serialized string.
+ *
+ * @param string $value
+ *
+ * @throws InvalidFormatException
+ *
+ * @return static
+ */
+ public static function fromSerialized($value)
+ {
+ $instance = @unserialize((string) $value);
+
+ if (!$instance instanceof static) {
+ throw new InvalidFormatException("Invalid serialized value: $value");
+ }
+
+ return $instance;
+ }
+
+ /**
+ * The __set_state handler.
+ *
+ * @param string|array $dump
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public static function __set_state($dump)
+ {
+ if (\is_string($dump)) {
+ return static::parse($dump);
+ }
+
+ /** @var \DateTimeInterface $date */
+ $date = get_parent_class(static::class) && method_exists(parent::class, '__set_state')
+ ? parent::__set_state((array) $dump)
+ : (object) $dump;
+
+ return static::instance($date);
+ }
+
+ /**
+ * Returns the list of properties to dump on serialize() called on.
+ *
+ * @return array
+ */
+ public function __sleep()
+ {
+ $properties = $this->getSleepProperties();
+
+ if ($this->localTranslator ?? null) {
+ $properties[] = 'dumpLocale';
+ $this->dumpLocale = $this->locale ?? null;
+ }
+
+ return $properties;
+ }
+
+ /**
+ * Set locale if specified on unserialize() called.
+ */
+ #[ReturnTypeWillChange]
+ public function __wakeup()
+ {
+ if (get_parent_class() && method_exists(parent::class, '__wakeup')) {
+ // @codeCoverageIgnoreStart
+ try {
+ parent::__wakeup();
+ } catch (Throwable $exception) {
+ // FatalError occurs when calling msgpack_unpack() in PHP 7.4 or later.
+ ['date' => $date, 'timezone' => $timezone] = $this->dumpDateProperties;
+ parent::__construct($date, unserialize($timezone));
+ }
+ // @codeCoverageIgnoreEnd
+ }
+
+ $this->constructedObjectId = spl_object_hash($this);
+
+ if (isset($this->dumpLocale)) {
+ $this->locale($this->dumpLocale);
+ $this->dumpLocale = null;
+ }
+
+ $this->cleanupDumpProperties();
+ }
+
+ /**
+ * Prepare the object for JSON serialization.
+ *
+ * @return array|string
+ */
+ #[ReturnTypeWillChange]
+ public function jsonSerialize()
+ {
+ $serializer = $this->localSerializer ?? static::$serializer;
+
+ if ($serializer) {
+ return \is_string($serializer)
+ ? $this->rawFormat($serializer)
+ : $serializer($this);
+ }
+
+ return $this->toJSON();
+ }
+
+ /**
+ * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
+ * You should rather transform Carbon object before the serialization.
+ *
+ * JSON serialize all Carbon instances using the given callback.
+ *
+ * @param callable $callback
+ *
+ * @return void
+ */
+ public static function serializeUsing($callback)
+ {
+ static::$serializer = $callback;
+ }
+
+ /**
+ * Cleanup properties attached to the public scope of DateTime when a dump of the date is requested.
+ * foreach ($date as $_) {}
+ * serializer($date)
+ * var_export($date)
+ * get_object_vars($date)
+ */
+ public function cleanupDumpProperties()
+ {
+ foreach ($this->dumpProperties as $property) {
+ if (isset($this->$property)) {
+ unset($this->$property);
+ }
+ }
+
+ return $this;
+ }
+
+ private function getSleepProperties(): array
+ {
+ $properties = $this->dumpProperties;
+
+ // @codeCoverageIgnoreStart
+ if (!\extension_loaded('msgpack')) {
+ return $properties;
+ }
+
+ if (isset($this->constructedObjectId)) {
+ $this->dumpDateProperties = [
+ 'date' => $this->format('Y-m-d H:i:s.u'),
+ 'timezone' => serialize($this->timezone ?? null),
+ ];
+
+ $properties[] = 'dumpDateProperties';
+ }
+
+ return $properties;
+ // @codeCoverageIgnoreEnd
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Test.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Test.php
new file mode 100644
index 0000000..d998974
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Test.php
@@ -0,0 +1,157 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Closure;
+use DateTimeImmutable;
+
+trait Test
+{
+ ///////////////////////////////////////////////////////////////////
+ ///////////////////////// TESTING AIDS ////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * A test Carbon instance to be returned when now instances are created.
+ *
+ * @var static
+ */
+ protected static $testNow;
+
+ /**
+ * Set a Carbon instance (real or mock) to be returned when a "now"
+ * instance is created. The provided instance will be returned
+ * specifically under the following conditions:
+ * - A call to the static now() method, ex. Carbon::now()
+ * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
+ * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
+ * - When a string containing the desired time is passed to Carbon::parse().
+ *
+ * Note the timezone parameter was left out of the examples above and
+ * has no affect as the mock value will be returned regardless of its value.
+ *
+ * To clear the test instance call this method using the default
+ * parameter of null.
+ *
+ * /!\ Use this method for unit tests only.
+ *
+ * @param Closure|static|string|false|null $testNow real or mock Carbon instance
+ */
+ public static function setTestNow($testNow = null)
+ {
+ if ($testNow === false) {
+ $testNow = null;
+ }
+
+ static::$testNow = \is_string($testNow) ? static::parse($testNow) : $testNow;
+ }
+
+ /**
+ * Temporarily sets a static date to be used within the callback.
+ * Using setTestNow to set the date, executing the callback, then
+ * clearing the test instance.
+ *
+ * /!\ Use this method for unit tests only.
+ *
+ * @param Closure|static|string|false|null $testNow real or mock Carbon instance
+ * @param Closure|null $callback
+ *
+ * @return mixed
+ */
+ public static function withTestNow($testNow = null, $callback = null)
+ {
+ static::setTestNow($testNow);
+ $result = $callback();
+ static::setTestNow();
+
+ return $result;
+ }
+
+ /**
+ * Get the Carbon instance (real or mock) to be returned when a "now"
+ * instance is created.
+ *
+ * @return Closure|static the current instance used for testing
+ */
+ public static function getTestNow()
+ {
+ return static::$testNow;
+ }
+
+ /**
+ * Determine if there is a valid test instance set. A valid test instance
+ * is anything that is not null.
+ *
+ * @return bool true if there is a test instance, otherwise false
+ */
+ public static function hasTestNow()
+ {
+ return static::getTestNow() !== null;
+ }
+
+ /**
+ * Return the given timezone and set it to the test instance if not null.
+ * If null, get the timezone from the test instance and return it.
+ *
+ * @param string|\DateTimeZone $tz
+ * @param \Carbon\CarbonInterface $testInstance
+ *
+ * @return string|\DateTimeZone
+ */
+ protected static function handleMockTimezone($tz, &$testInstance)
+ {
+ //shift the time according to the given time zone
+ if ($tz !== null && $tz !== static::getMockedTestNow($tz)->getTimezone()) {
+ $testInstance = $testInstance->setTimezone($tz);
+
+ return $tz;
+ }
+
+ return $testInstance->getTimezone();
+ }
+
+ /**
+ * Get the mocked date passed in setTestNow() and if it's a Closure, execute it.
+ *
+ * @param string|\DateTimeZone $tz
+ *
+ * @return \Carbon\CarbonImmutable|\Carbon\Carbon|null
+ */
+ protected static function getMockedTestNow($tz)
+ {
+ $testNow = static::getTestNow();
+
+ if ($testNow instanceof Closure) {
+ $realNow = new DateTimeImmutable('now');
+ $testNow = $testNow(static::parse(
+ $realNow->format('Y-m-d H:i:s.u'),
+ $tz ?: $realNow->getTimezone()
+ ));
+ }
+ /* @var \Carbon\CarbonImmutable|\Carbon\Carbon|null $testNow */
+
+ return $testNow;
+ }
+
+ protected static function mockConstructorParameters(&$time, &$tz)
+ {
+ /** @var \Carbon\CarbonImmutable|\Carbon\Carbon $testInstance */
+ $testInstance = clone static::getMockedTestNow($tz);
+
+ $tz = static::handleMockTimezone($tz, $testInstance);
+
+ if (static::hasRelativeKeywords($time)) {
+ $testInstance = $testInstance->modify($time);
+ }
+
+ $time = $testInstance instanceof self ? $testInstance->rawFormat(static::MOCK_DATETIME_FORMAT) : $testInstance->format(static::MOCK_DATETIME_FORMAT);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Timestamp.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Timestamp.php
new file mode 100644
index 0000000..35d45aa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Timestamp.php
@@ -0,0 +1,197 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+/**
+ * Trait Timestamp.
+ */
+trait Timestamp
+{
+ /**
+ * Create a Carbon instance from a timestamp and set the timezone (use default one if not specified).
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $timestamp
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function createFromTimestamp($timestamp, $tz = null)
+ {
+ return static::createFromTimestampUTC($timestamp)->setTimezone($tz);
+ }
+
+ /**
+ * Create a Carbon instance from an timestamp keeping the timezone to UTC.
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $timestamp
+ *
+ * @return static
+ */
+ public static function createFromTimestampUTC($timestamp)
+ {
+ [$integer, $decimal] = self::getIntegerAndDecimalParts($timestamp);
+ $delta = floor($decimal / static::MICROSECONDS_PER_SECOND);
+ $integer += $delta;
+ $decimal -= $delta * static::MICROSECONDS_PER_SECOND;
+ $decimal = str_pad((string) $decimal, 6, '0', STR_PAD_LEFT);
+
+ return static::rawCreateFromFormat('U u', "$integer $decimal");
+ }
+
+ /**
+ * Create a Carbon instance from a timestamp in milliseconds.
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $timestamp
+ *
+ * @return static
+ */
+ public static function createFromTimestampMsUTC($timestamp)
+ {
+ [$milliseconds, $microseconds] = self::getIntegerAndDecimalParts($timestamp, 3);
+ $sign = $milliseconds < 0 || $milliseconds === 0.0 && $microseconds < 0 ? -1 : 1;
+ $milliseconds = abs($milliseconds);
+ $microseconds = $sign * abs($microseconds) + static::MICROSECONDS_PER_MILLISECOND * ($milliseconds % static::MILLISECONDS_PER_SECOND);
+ $seconds = $sign * floor($milliseconds / static::MILLISECONDS_PER_SECOND);
+ $delta = floor($microseconds / static::MICROSECONDS_PER_SECOND);
+ $seconds += $delta;
+ $microseconds -= $delta * static::MICROSECONDS_PER_SECOND;
+ $microseconds = str_pad($microseconds, 6, '0', STR_PAD_LEFT);
+
+ return static::rawCreateFromFormat('U u', "$seconds $microseconds");
+ }
+
+ /**
+ * Create a Carbon instance from a timestamp in milliseconds.
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $timestamp
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function createFromTimestampMs($timestamp, $tz = null)
+ {
+ return static::createFromTimestampMsUTC($timestamp)
+ ->setTimezone($tz);
+ }
+
+ /**
+ * Set the instance's timestamp.
+ *
+ * Timestamp input can be given as int, float or a string containing one or more numbers.
+ *
+ * @param float|int|string $unixTimestamp
+ *
+ * @return static
+ */
+ public function timestamp($unixTimestamp)
+ {
+ return $this->setTimestamp($unixTimestamp);
+ }
+
+ /**
+ * Returns a timestamp rounded with the given precision (6 by default).
+ *
+ * @example getPreciseTimestamp() 1532087464437474 (microsecond maximum precision)
+ * @example getPreciseTimestamp(6) 1532087464437474
+ * @example getPreciseTimestamp(5) 153208746443747 (1/100000 second precision)
+ * @example getPreciseTimestamp(4) 15320874644375 (1/10000 second precision)
+ * @example getPreciseTimestamp(3) 1532087464437 (millisecond precision)
+ * @example getPreciseTimestamp(2) 153208746444 (1/100 second precision)
+ * @example getPreciseTimestamp(1) 15320874644 (1/10 second precision)
+ * @example getPreciseTimestamp(0) 1532087464 (second precision)
+ * @example getPreciseTimestamp(-1) 153208746 (10 second precision)
+ * @example getPreciseTimestamp(-2) 15320875 (100 second precision)
+ *
+ * @param int $precision
+ *
+ * @return float
+ */
+ public function getPreciseTimestamp($precision = 6)
+ {
+ return round($this->rawFormat('Uu') / pow(10, 6 - $precision));
+ }
+
+ /**
+ * Returns the milliseconds timestamps used amongst other by Date javascript objects.
+ *
+ * @return float
+ */
+ public function valueOf()
+ {
+ return $this->getPreciseTimestamp(3);
+ }
+
+ /**
+ * Returns the timestamp with millisecond precision.
+ *
+ * @return int
+ */
+ public function getTimestampMs()
+ {
+ return (int) $this->getPreciseTimestamp(3);
+ }
+
+ /**
+ * @alias getTimestamp
+ *
+ * Returns the UNIX timestamp for the current date.
+ *
+ * @return int
+ */
+ public function unix()
+ {
+ return $this->getTimestamp();
+ }
+
+ /**
+ * Return an array with integer part digits and decimals digits split from one or more positive numbers
+ * (such as timestamps) as string with the given number of decimals (6 by default).
+ *
+ * By splitting integer and decimal, this method obtain a better precision than
+ * number_format when the input is a string.
+ *
+ * @param float|int|string $numbers one or more numbers
+ * @param int $decimals number of decimals precision (6 by default)
+ *
+ * @return array 0-index is integer part, 1-index is decimal part digits
+ */
+ private static function getIntegerAndDecimalParts($numbers, $decimals = 6)
+ {
+ if (\is_int($numbers) || \is_float($numbers)) {
+ $numbers = number_format($numbers, $decimals, '.', '');
+ }
+
+ $sign = str_starts_with($numbers, '-') ? -1 : 1;
+ $integer = 0;
+ $decimal = 0;
+
+ foreach (preg_split('`[^0-9.]+`', $numbers) as $chunk) {
+ [$integerPart, $decimalPart] = explode('.', "$chunk.");
+
+ $integer += (int) $integerPart;
+ $decimal += (float) ("0.$decimalPart");
+ }
+
+ $overflow = floor($decimal);
+ $integer += $overflow;
+ $decimal -= $overflow;
+
+ return [$sign * $integer, $decimal === 0.0 ? 0.0 : $sign * round($decimal * pow(10, $decimals))];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Units.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Units.php
new file mode 100644
index 0000000..aec85ab
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Units.php
@@ -0,0 +1,417 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+use Carbon\CarbonConverterInterface;
+use Carbon\CarbonInterface;
+use Carbon\CarbonInterval;
+use Carbon\Exceptions\UnitException;
+use Closure;
+use DateInterval;
+use ReturnTypeWillChange;
+
+/**
+ * Trait Units.
+ *
+ * Add, subtract and set units.
+ */
+trait Units
+{
+ /**
+ * Add seconds to the instance using timestamp. Positive $value travels
+ * forward while negative $value travels into the past.
+ *
+ * @param string $unit
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addRealUnit($unit, $value = 1)
+ {
+ switch ($unit) {
+ // @call addRealUnit
+ case 'micro':
+
+ // @call addRealUnit
+ case 'microsecond':
+ /* @var CarbonInterface $this */
+ $diff = $this->microsecond + $value;
+ $time = $this->getTimestamp();
+ $seconds = (int) floor($diff / static::MICROSECONDS_PER_SECOND);
+ $time += $seconds;
+ $diff -= $seconds * static::MICROSECONDS_PER_SECOND;
+ $microtime = str_pad((string) $diff, 6, '0', STR_PAD_LEFT);
+ $tz = $this->tz;
+
+ return $this->tz('UTC')->modify("@$time.$microtime")->tz($tz);
+
+ // @call addRealUnit
+ case 'milli':
+ // @call addRealUnit
+ case 'millisecond':
+ return $this->addRealUnit('microsecond', $value * static::MICROSECONDS_PER_MILLISECOND);
+
+ break;
+
+ // @call addRealUnit
+ case 'second':
+ break;
+
+ // @call addRealUnit
+ case 'minute':
+ $value *= static::SECONDS_PER_MINUTE;
+
+ break;
+
+ // @call addRealUnit
+ case 'hour':
+ $value *= static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
+
+ break;
+
+ // @call addRealUnit
+ case 'day':
+ $value *= static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
+
+ break;
+
+ // @call addRealUnit
+ case 'week':
+ $value *= static::DAYS_PER_WEEK * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
+
+ break;
+
+ // @call addRealUnit
+ case 'month':
+ $value *= 30 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
+
+ break;
+
+ // @call addRealUnit
+ case 'quarter':
+ $value *= static::MONTHS_PER_QUARTER * 30 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
+
+ break;
+
+ // @call addRealUnit
+ case 'year':
+ $value *= 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
+
+ break;
+
+ // @call addRealUnit
+ case 'decade':
+ $value *= static::YEARS_PER_DECADE * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
+
+ break;
+
+ // @call addRealUnit
+ case 'century':
+ $value *= static::YEARS_PER_CENTURY * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
+
+ break;
+
+ // @call addRealUnit
+ case 'millennium':
+ $value *= static::YEARS_PER_MILLENNIUM * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;
+
+ break;
+
+ default:
+ if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
+ throw new UnitException("Invalid unit for real timestamp add/sub: '$unit'");
+ }
+
+ return $this;
+ }
+
+ /* @var CarbonInterface $this */
+ return $this->setTimestamp((int) ($this->getTimestamp() + $value));
+ }
+
+ public function subRealUnit($unit, $value = 1)
+ {
+ return $this->addRealUnit($unit, -$value);
+ }
+
+ /**
+ * Returns true if a property can be changed via setter.
+ *
+ * @param string $unit
+ *
+ * @return bool
+ */
+ public static function isModifiableUnit($unit)
+ {
+ static $modifiableUnits = [
+ // @call addUnit
+ 'millennium',
+ // @call addUnit
+ 'century',
+ // @call addUnit
+ 'decade',
+ // @call addUnit
+ 'quarter',
+ // @call addUnit
+ 'week',
+ // @call addUnit
+ 'weekday',
+ ];
+
+ return \in_array($unit, $modifiableUnits) || \in_array($unit, static::$units);
+ }
+
+ /**
+ * Call native PHP DateTime/DateTimeImmutable add() method.
+ *
+ * @param DateInterval $interval
+ *
+ * @return static
+ */
+ public function rawAdd(DateInterval $interval)
+ {
+ return parent::add($interval);
+ }
+
+ /**
+ * Add given units or interval to the current instance.
+ *
+ * @example $date->add('hour', 3)
+ * @example $date->add(15, 'days')
+ * @example $date->add(CarbonInterval::days(4))
+ *
+ * @param string|DateInterval|Closure|CarbonConverterInterface $unit
+ * @param int $value
+ * @param bool|null $overflow
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function add($unit, $value = 1, $overflow = null)
+ {
+ if (\is_string($unit) && \func_num_args() === 1) {
+ $unit = CarbonInterval::make($unit);
+ }
+
+ // Can be removed if https://bugs.php.net/bug.php?id=81106
+ // is fixed
+ // @codeCoverageIgnoreStart
+ if (
+ $unit instanceof DateInterval &&
+ version_compare(PHP_VERSION, '8.1.0-dev', '>=') &&
+ ($unit->f < 0 || $unit->f >= 1)
+ ) {
+ $unit = clone $unit;
+ $seconds = floor($unit->f);
+ $unit->f -= $seconds;
+ $unit->s += (int) $seconds;
+ }
+ // @codeCoverageIgnoreEnd
+
+ if ($unit instanceof CarbonConverterInterface) {
+ return $this->resolveCarbon($unit->convertDate($this, false));
+ }
+
+ if ($unit instanceof Closure) {
+ return $this->resolveCarbon($unit($this, false));
+ }
+
+ if ($unit instanceof DateInterval) {
+ return parent::add($unit);
+ }
+
+ if (is_numeric($unit)) {
+ [$value, $unit] = [$unit, $value];
+ }
+
+ return $this->addUnit($unit, $value, $overflow);
+ }
+
+ /**
+ * Add given units to the current instance.
+ *
+ * @param string $unit
+ * @param int $value
+ * @param bool|null $overflow
+ *
+ * @return static
+ */
+ public function addUnit($unit, $value = 1, $overflow = null)
+ {
+ $date = $this;
+
+ if (!is_numeric($value) || !(float) $value) {
+ return $date->isMutable() ? $date : $date->avoidMutation();
+ }
+
+ $metaUnits = [
+ 'millennium' => [static::YEARS_PER_MILLENNIUM, 'year'],
+ 'century' => [static::YEARS_PER_CENTURY, 'year'],
+ 'decade' => [static::YEARS_PER_DECADE, 'year'],
+ 'quarter' => [static::MONTHS_PER_QUARTER, 'month'],
+ ];
+
+ if (isset($metaUnits[$unit])) {
+ [$factor, $unit] = $metaUnits[$unit];
+ $value *= $factor;
+ }
+
+ if ($unit === 'weekday') {
+ $weekendDays = static::getWeekendDays();
+
+ if ($weekendDays !== [static::SATURDAY, static::SUNDAY]) {
+ $absoluteValue = abs($value);
+ $sign = $value / max(1, $absoluteValue);
+ $weekDaysCount = 7 - min(6, \count(array_unique($weekendDays)));
+ $weeks = floor($absoluteValue / $weekDaysCount);
+
+ for ($diff = $absoluteValue % $weekDaysCount; $diff; $diff--) {
+ /** @var static $date */
+ $date = $date->addDays($sign);
+
+ while (\in_array($date->dayOfWeek, $weekendDays)) {
+ $date = $date->addDays($sign);
+ }
+ }
+
+ $value = $weeks * $sign;
+ $unit = 'week';
+ }
+
+ $timeString = $date->toTimeString();
+ } elseif ($canOverflow = \in_array($unit, [
+ 'month',
+ 'year',
+ ]) && ($overflow === false || (
+ $overflow === null &&
+ ($ucUnit = ucfirst($unit).'s') &&
+ !($this->{'local'.$ucUnit.'Overflow'} ?? static::{'shouldOverflow'.$ucUnit}())
+ ))) {
+ $day = $date->day;
+ }
+
+ $value = (int) $value;
+
+ if ($unit === 'milli' || $unit === 'millisecond') {
+ $unit = 'microsecond';
+ $value *= static::MICROSECONDS_PER_MILLISECOND;
+ }
+
+ // Work-around for bug https://bugs.php.net/bug.php?id=75642
+ if ($unit === 'micro' || $unit === 'microsecond') {
+ $microseconds = $this->micro + $value;
+ $second = (int) floor($microseconds / static::MICROSECONDS_PER_SECOND);
+ $microseconds %= static::MICROSECONDS_PER_SECOND;
+ if ($microseconds < 0) {
+ $microseconds += static::MICROSECONDS_PER_SECOND;
+ }
+ $date = $date->microseconds($microseconds);
+ $unit = 'second';
+ $value = $second;
+ }
+ $date = $date->modify("$value $unit");
+
+ if (isset($timeString)) {
+ return $date->setTimeFromTimeString($timeString);
+ }
+
+ if (isset($canOverflow, $day) && $canOverflow && $day !== $date->day) {
+ $date = $date->modify('last day of previous month');
+ }
+
+ return $date;
+ }
+
+ /**
+ * Subtract given units to the current instance.
+ *
+ * @param string $unit
+ * @param int $value
+ * @param bool|null $overflow
+ *
+ * @return static
+ */
+ public function subUnit($unit, $value = 1, $overflow = null)
+ {
+ return $this->addUnit($unit, -$value, $overflow);
+ }
+
+ /**
+ * Call native PHP DateTime/DateTimeImmutable sub() method.
+ *
+ * @param DateInterval $interval
+ *
+ * @return static
+ */
+ public function rawSub(DateInterval $interval)
+ {
+ return parent::sub($interval);
+ }
+
+ /**
+ * Subtract given units or interval to the current instance.
+ *
+ * @example $date->sub('hour', 3)
+ * @example $date->sub(15, 'days')
+ * @example $date->sub(CarbonInterval::days(4))
+ *
+ * @param string|DateInterval|Closure|CarbonConverterInterface $unit
+ * @param int $value
+ * @param bool|null $overflow
+ *
+ * @return static
+ */
+ #[ReturnTypeWillChange]
+ public function sub($unit, $value = 1, $overflow = null)
+ {
+ if (\is_string($unit) && \func_num_args() === 1) {
+ $unit = CarbonInterval::make($unit);
+ }
+
+ if ($unit instanceof CarbonConverterInterface) {
+ return $this->resolveCarbon($unit->convertDate($this, true));
+ }
+
+ if ($unit instanceof Closure) {
+ return $this->resolveCarbon($unit($this, true));
+ }
+
+ if ($unit instanceof DateInterval) {
+ return parent::sub($unit);
+ }
+
+ if (is_numeric($unit)) {
+ [$value, $unit] = [$unit, $value];
+ }
+
+ return $this->addUnit($unit, -(float) $value, $overflow);
+ }
+
+ /**
+ * Subtract given units or interval to the current instance.
+ *
+ * @see sub()
+ *
+ * @param string|DateInterval $unit
+ * @param int $value
+ * @param bool|null $overflow
+ *
+ * @return static
+ */
+ public function subtract($unit, $value = 1, $overflow = null)
+ {
+ if (\is_string($unit) && \func_num_args() === 1) {
+ $unit = CarbonInterval::make($unit);
+ }
+
+ return $this->sub($unit, $value, $overflow);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Week.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Week.php
new file mode 100644
index 0000000..64cece7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Week.php
@@ -0,0 +1,218 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon\Traits;
+
+/**
+ * Trait Week.
+ *
+ * week and ISO week number, year and count in year.
+ *
+ * Depends on the following properties:
+ *
+ * @property int $daysInYear
+ * @property int $dayOfWeek
+ * @property int $dayOfYear
+ * @property int $year
+ *
+ * Depends on the following methods:
+ *
+ * @method static addWeeks(int $weeks = 1)
+ * @method static copy()
+ * @method static dayOfYear(int $dayOfYear)
+ * @method string getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
+ * @method static next(int|string $day = null)
+ * @method static startOfWeek(int $day = 1)
+ * @method static subWeeks(int $weeks = 1)
+ * @method static year(int $year = null)
+ */
+trait Week
+{
+ /**
+ * Set/get the week number of year using given first day of week and first
+ * day of year included in the first week. Or use ISO format if no settings
+ * given.
+ *
+ * @param int|null $year if null, act as a getter, if not null, set the year and return current instance.
+ * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
+ * @param int|null $dayOfYear first day of year included in the week #1
+ *
+ * @return int|static
+ */
+ public function isoWeekYear($year = null, $dayOfWeek = null, $dayOfYear = null)
+ {
+ return $this->weekYear(
+ $year,
+ $dayOfWeek ?? 1,
+ $dayOfYear ?? 4
+ );
+ }
+
+ /**
+ * Set/get the week number of year using given first day of week and first
+ * day of year included in the first week. Or use US format if no settings
+ * given (Sunday / Jan 6).
+ *
+ * @param int|null $year if null, act as a getter, if not null, set the year and return current instance.
+ * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
+ * @param int|null $dayOfYear first day of year included in the week #1
+ *
+ * @return int|static
+ */
+ public function weekYear($year = null, $dayOfWeek = null, $dayOfYear = null)
+ {
+ $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
+ $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;
+
+ if ($year !== null) {
+ $year = (int) round($year);
+
+ if ($this->weekYear(null, $dayOfWeek, $dayOfYear) === $year) {
+ return $this->avoidMutation();
+ }
+
+ $week = $this->week(null, $dayOfWeek, $dayOfYear);
+ $day = $this->dayOfWeek;
+ $date = $this->year($year);
+ switch ($date->weekYear(null, $dayOfWeek, $dayOfYear) - $year) {
+ case 1:
+ $date = $date->subWeeks(26);
+
+ break;
+ case -1:
+ $date = $date->addWeeks(26);
+
+ break;
+ }
+
+ $date = $date->addWeeks($week - $date->week(null, $dayOfWeek, $dayOfYear))->startOfWeek($dayOfWeek);
+
+ if ($date->dayOfWeek === $day) {
+ return $date;
+ }
+
+ return $date->next($day);
+ }
+
+ $year = $this->year;
+ $day = $this->dayOfYear;
+ $date = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+
+ if ($date->year === $year && $day < $date->dayOfYear) {
+ return $year - 1;
+ }
+
+ $date = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+
+ if ($date->year === $year && $day >= $date->dayOfYear) {
+ return $year + 1;
+ }
+
+ return $year;
+ }
+
+ /**
+ * Get the number of weeks of the current week-year using given first day of week and first
+ * day of year included in the first week. Or use ISO format if no settings
+ * given.
+ *
+ * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
+ * @param int|null $dayOfYear first day of year included in the week #1
+ *
+ * @return int
+ */
+ public function isoWeeksInYear($dayOfWeek = null, $dayOfYear = null)
+ {
+ return $this->weeksInYear(
+ $dayOfWeek ?? 1,
+ $dayOfYear ?? 4
+ );
+ }
+
+ /**
+ * Get the number of weeks of the current week-year using given first day of week and first
+ * day of year included in the first week. Or use US format if no settings
+ * given (Sunday / Jan 6).
+ *
+ * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
+ * @param int|null $dayOfYear first day of year included in the week #1
+ *
+ * @return int
+ */
+ public function weeksInYear($dayOfWeek = null, $dayOfYear = null)
+ {
+ $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
+ $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;
+ $year = $this->year;
+ $start = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+ $startDay = $start->dayOfYear;
+ if ($start->year !== $year) {
+ $startDay -= $start->daysInYear;
+ }
+ $end = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+ $endDay = $end->dayOfYear;
+ if ($end->year !== $year) {
+ $endDay += $this->daysInYear;
+ }
+
+ return (int) round(($endDay - $startDay) / 7);
+ }
+
+ /**
+ * Get/set the week number using given first day of week and first
+ * day of year included in the first week. Or use US format if no settings
+ * given (Sunday / Jan 6).
+ *
+ * @param int|null $week
+ * @param int|null $dayOfWeek
+ * @param int|null $dayOfYear
+ *
+ * @return int|static
+ */
+ public function week($week = null, $dayOfWeek = null, $dayOfYear = null)
+ {
+ $date = $this;
+ $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
+ $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;
+
+ if ($week !== null) {
+ return $date->addWeeks(round($week) - $this->week(null, $dayOfWeek, $dayOfYear));
+ }
+
+ $start = $date->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+ $end = $date->avoidMutation()->startOfWeek($dayOfWeek);
+ if ($start > $end) {
+ $start = $start->subWeeks(26)->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+ }
+ $week = (int) ($start->diffInDays($end) / 7 + 1);
+
+ return $week > $end->weeksInYear($dayOfWeek, $dayOfYear) ? 1 : $week;
+ }
+
+ /**
+ * Get/set the week number using given first day of week and first
+ * day of year included in the first week. Or use ISO format if no settings
+ * given.
+ *
+ * @param int|null $week
+ * @param int|null $dayOfWeek
+ * @param int|null $dayOfYear
+ *
+ * @return int|static
+ */
+ public function isoWeek($week = null, $dayOfWeek = null, $dayOfYear = null)
+ {
+ return $this->week(
+ $week,
+ $dayOfWeek ?? 1,
+ $dayOfYear ?? 4
+ );
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Translator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Translator.php
new file mode 100644
index 0000000..9af48eb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Translator.php
@@ -0,0 +1,403 @@
+<?php
+
+/**
+ * This file is part of the Carbon package.
+ *
+ * (c) Brian Nesbitt <brian@nesbot.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Carbon;
+
+use Closure;
+use ReflectionException;
+use ReflectionFunction;
+use Symfony\Component\Translation;
+
+class Translator extends Translation\Translator
+{
+ /**
+ * Translator singletons for each language.
+ *
+ * @var array
+ */
+ protected static $singletons = [];
+
+ /**
+ * List of custom localized messages.
+ *
+ * @var array
+ */
+ protected $messages = [];
+
+ /**
+ * List of custom directories that contain translation files.
+ *
+ * @var string[]
+ */
+ protected $directories = [];
+
+ /**
+ * Set to true while constructing.
+ *
+ * @var bool
+ */
+ protected $initializing = false;
+
+ /**
+ * List of locales aliases.
+ *
+ * @var string[]
+ */
+ protected $aliases = [
+ 'me' => 'sr_Latn_ME',
+ 'scr' => 'sh',
+ ];
+
+ /**
+ * Return a singleton instance of Translator.
+ *
+ * @param string|null $locale optional initial locale ("en" - english by default)
+ *
+ * @return static
+ */
+ public static function get($locale = null)
+ {
+ $locale = $locale ?: 'en';
+
+ if (!isset(static::$singletons[$locale])) {
+ static::$singletons[$locale] = new static($locale ?: 'en');
+ }
+
+ return static::$singletons[$locale];
+ }
+
+ public function __construct($locale, Translation\Formatter\MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false)
+ {
+ $this->initializing = true;
+ $this->directories = [__DIR__.'/Lang'];
+ $this->addLoader('array', new Translation\Loader\ArrayLoader());
+ parent::__construct($locale, $formatter, $cacheDir, $debug);
+ $this->initializing = false;
+ }
+
+ /**
+ * Returns the list of directories translation files are searched in.
+ *
+ * @return array
+ */
+ public function getDirectories(): array
+ {
+ return $this->directories;
+ }
+
+ /**
+ * Set list of directories translation files are searched in.
+ *
+ * @param array $directories new directories list
+ *
+ * @return $this
+ */
+ public function setDirectories(array $directories)
+ {
+ $this->directories = $directories;
+
+ return $this;
+ }
+
+ /**
+ * Add a directory to the list translation files are searched in.
+ *
+ * @param string $directory new directory
+ *
+ * @return $this
+ */
+ public function addDirectory(string $directory)
+ {
+ $this->directories[] = $directory;
+
+ return $this;
+ }
+
+ /**
+ * Remove a directory from the list translation files are searched in.
+ *
+ * @param string $directory directory path
+ *
+ * @return $this
+ */
+ public function removeDirectory(string $directory)
+ {
+ $search = rtrim(strtr($directory, '\\', '/'), '/');
+
+ return $this->setDirectories(array_filter($this->getDirectories(), function ($item) use ($search) {
+ return rtrim(strtr($item, '\\', '/'), '/') !== $search;
+ }));
+ }
+
+ /**
+ * Returns the translation.
+ *
+ * @param string $id
+ * @param array $parameters
+ * @param string $domain
+ * @param string $locale
+ *
+ * @return string
+ */
+ public function trans($id, array $parameters = [], $domain = null, $locale = null)
+ {
+ if ($domain === null) {
+ $domain = 'messages';
+ }
+
+ $format = $this->getCatalogue($locale)->get((string) $id, $domain);
+
+ if ($format instanceof Closure) {
+ // @codeCoverageIgnoreStart
+ try {
+ $count = (new ReflectionFunction($format))->getNumberOfRequiredParameters();
+ } catch (ReflectionException $exception) {
+ $count = 0;
+ }
+ // @codeCoverageIgnoreEnd
+
+ return $format(
+ ...array_values($parameters),
+ ...array_fill(0, max(0, $count - \count($parameters)), null)
+ );
+ }
+
+ return parent::trans($id, $parameters, $domain, $locale);
+ }
+
+ /**
+ * Reset messages of a locale (all locale if no locale passed).
+ * Remove custom messages and reload initial messages from matching
+ * file in Lang directory.
+ *
+ * @param string|null $locale
+ *
+ * @return bool
+ */
+ public function resetMessages($locale = null)
+ {
+ if ($locale === null) {
+ $this->messages = [];
+
+ return true;
+ }
+
+ foreach ($this->getDirectories() as $directory) {
+ $data = @include sprintf('%s/%s.php', rtrim($directory, '\\/'), $locale);
+
+ if ($data !== false) {
+ $this->messages[$locale] = $data;
+ $this->addResource('array', $this->messages[$locale], $locale);
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the list of files matching a given locale prefix (or all if empty).
+ *
+ * @param string $prefix prefix required to filter result
+ *
+ * @return array
+ */
+ public function getLocalesFiles($prefix = '')
+ {
+ $files = [];
+
+ foreach ($this->getDirectories() as $directory) {
+ $directory = rtrim($directory, '\\/');
+
+ foreach (glob("$directory/$prefix*.php") as $file) {
+ $files[] = $file;
+ }
+ }
+
+ return array_unique($files);
+ }
+
+ /**
+ * Returns the list of internally available locales and already loaded custom locales.
+ * (It will ignore custom translator dynamic loading.)
+ *
+ * @param string $prefix prefix required to filter result
+ *
+ * @return array
+ */
+ public function getAvailableLocales($prefix = '')
+ {
+ $locales = [];
+ foreach ($this->getLocalesFiles($prefix) as $file) {
+ $locales[] = substr($file, strrpos($file, '/') + 1, -4);
+ }
+
+ return array_unique(array_merge($locales, array_keys($this->messages)));
+ }
+
+ /**
+ * Init messages language from matching file in Lang directory.
+ *
+ * @param string $locale
+ *
+ * @return bool
+ */
+ protected function loadMessagesFromFile($locale)
+ {
+ if (isset($this->messages[$locale])) {
+ return true;
+ }
+
+ return $this->resetMessages($locale);
+ }
+
+ /**
+ * Set messages of a locale and take file first if present.
+ *
+ * @param string $locale
+ * @param array $messages
+ *
+ * @return $this
+ */
+ public function setMessages($locale, $messages)
+ {
+ $this->loadMessagesFromFile($locale);
+ $this->addResource('array', $messages, $locale);
+ $this->messages[$locale] = array_merge(
+ isset($this->messages[$locale]) ? $this->messages[$locale] : [],
+ $messages
+ );
+
+ return $this;
+ }
+
+ /**
+ * Set messages of the current locale and take file first if present.
+ *
+ * @param array $messages
+ *
+ * @return $this
+ */
+ public function setTranslations($messages)
+ {
+ return $this->setMessages($this->getLocale(), $messages);
+ }
+
+ /**
+ * Get messages of a locale, if none given, return all the
+ * languages.
+ *
+ * @param string|null $locale
+ *
+ * @return array
+ */
+ public function getMessages($locale = null)
+ {
+ return $locale === null ? $this->messages : $this->messages[$locale];
+ }
+
+ /**
+ * Set the current translator locale and indicate if the source locale file exists
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public function setLocale($locale)
+ {
+ $locale = preg_replace_callback('/[-_]([a-z]{2,}|[0-9]{2,})/', function ($matches) {
+ // _2-letters or YUE is a region, _3+-letters is a variant
+ $upper = strtoupper($matches[1]);
+
+ if ($upper === 'YUE' || $upper === 'ISO' || \strlen($upper) < 3) {
+ return "_$upper";
+ }
+
+ return '_'.ucfirst($matches[1]);
+ }, strtolower($locale));
+
+ $previousLocale = $this->getLocale();
+
+ if ($previousLocale === $locale && isset($this->messages[$locale])) {
+ return true;
+ }
+
+ unset(static::$singletons[$previousLocale]);
+
+ if ($locale === 'auto') {
+ $completeLocale = setlocale(LC_TIME, '0');
+ $locale = preg_replace('/^([^_.-]+).*$/', '$1', $completeLocale);
+ $locales = $this->getAvailableLocales($locale);
+
+ $completeLocaleChunks = preg_split('/[_.-]+/', $completeLocale);
+
+ $getScore = function ($language) use ($completeLocaleChunks) {
+ return static::compareChunkLists($completeLocaleChunks, preg_split('/[_.-]+/', $language));
+ };
+
+ usort($locales, function ($first, $second) use ($getScore) {
+ return $getScore($second) <=> $getScore($first);
+ });
+
+ $locale = $locales[0];
+ }
+
+ if (isset($this->aliases[$locale])) {
+ $locale = $this->aliases[$locale];
+ }
+
+ // If subtag (ex: en_CA) first load the macro (ex: en) to have a fallback
+ if (str_contains($locale, '_') &&
+ $this->loadMessagesFromFile($macroLocale = preg_replace('/^([^_]+).*$/', '$1', $locale))
+ ) {
+ parent::setLocale($macroLocale);
+ }
+
+ if ($this->loadMessagesFromFile($locale) || $this->initializing) {
+ parent::setLocale($locale);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Show locale on var_dump().
+ *
+ * @return array
+ */
+ public function __debugInfo()
+ {
+ return [
+ 'locale' => $this->getLocale(),
+ ];
+ }
+
+ private static function compareChunkLists($referenceChunks, $chunks)
+ {
+ $score = 0;
+
+ foreach ($referenceChunks as $index => $chunk) {
+ if (!isset($chunks[$index])) {
+ $score++;
+
+ continue;
+ }
+
+ if (strtolower($chunks[$index]) === strtolower($chunk)) {
+ $score += 10;
+ }
+ }
+
+ return $score;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml
new file mode 100644
index 0000000..34c8210
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml
@@ -0,0 +1,60 @@
+name: CI
+
+on: [push]
+
+jobs:
+
+ tests:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ php: [7.2, 7.3, 7.4, 8.0]
+ dependency-version: [prefer-lowest, prefer-stable]
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v1
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ extensions: mailparse
+ coverage: none
+
+ - name: Install dependencies
+ run: composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest --no-progress
+
+ - name: Execute tests
+ run: vendor/bin/phpunit
+
+ php-cs:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v1
+
+ - name: Install dependencies
+ run: composer update --no-progress --ignore-platform-reqs
+
+ - name: Execute phpcs
+ run: vendor/bin/phpcs src tests --standard=psr2
+
+ coverage:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v1
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: 7.4
+ extensions: mailparse
+
+ - name: Install dependencies
+ run: composer update --prefer-dist --no-interaction --no-suggest --no-progress
+
+ - name: Execute code coverage
+ run: |
+ vendor/bin/phpunit --coverage-clover=coverage.xml --whitelist src
+ bash <(curl -s https://codecov.io/bash) -t ${{ secrets.COVERALLS_REPO_TOKEN }}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/README.md
index 68f997a..24a6e0e 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/README.md
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/README.md
@@ -1,6 +1,6 @@
# php-mime-mail-parser
-A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).
+A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).
It's the most effective php email parser around in terms of performance, foreign character encoding, attachment handling, and ease of use.
Internet Message Format RFC [822](https://tools.ietf.org/html/rfc822), [2822](https://tools.ietf.org/html/rfc2822), [5322](https://tools.ietf.org/html/rfc5322).
@@ -23,7 +23,7 @@
We use GitHub Actions, Codecov, Codacy to help ensure code quality. You can see real-time statistics below:
-[![Actions Status](https://wdp9fww0r9.execute-api.us-west-2.amazonaws.com/production/badge/php-mime-mail-parser/php-mime-mail-parser?style=flat-square)](https://wdp9fww0r9.execute-api.us-west-2.amazonaws.com/production/results/php-mime-mail-parser/php-mime-mail-parser)
+[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fphp-mime-mail-parser%2Fphp-mime-mail-parser%2Fbadge%3Fref%3Dmaster&style=flat-square)](https://actions-badge.atrox.dev/php-mime-mail-parser/php-mime-mail-parser/goto?ref=master)
[![Coverage](https://img.shields.io/codecov/c/gh/php-mime-mail-parser/php-mime-mail-parser?style=flat-square)](https://codecov.io/gh/php-mime-mail-parser/php-mime-mail-parser)
[![Code Quality](https://img.shields.io/codacy/grade/4e0e44fee21147ddbdd18ff976251875?style=flat-square)](https://app.codacy.com/app/php-mime-mail-parser/php-mime-mail-parser)
@@ -40,19 +40,20 @@
The following versions of PHP are supported:
-* PHP 7.1
* PHP 7.2
* PHP 7.3
+* PHP 7.4
Previous Versions:
| PHP Compatibility | Version |
| ------------- | ------------- |
-| HHVM | php-mime-mail-parser 2.11.1 |
-| PHP 5.4 | php-mime-mail-parser 2.11.1 |
-| PHP 5.5 | php-mime-mail-parser 2.11.1 |
+| HHVM | php-mime-mail-parser 2.11.1 |
+| PHP 5.4 | php-mime-mail-parser 2.11.1 |
+| PHP 5.5 | php-mime-mail-parser 2.11.1 |
| PHP 5.6 | php-mime-mail-parser 3.0.4 |
| PHP 7.0 | php-mime-mail-parser 3.0.4 |
+| PHP 7.1 | php-mime-mail-parser 5.0.5 |
Make sure you have the mailparse extension (http://php.net/manual/en/book.mailparse.php) properly installed. The command line `php -m | grep mailparse` need to return "mailparse".
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/composer.json
index a797183..e9861a2 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/composer.json
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/composer.json
@@ -1,7 +1,7 @@
{
"name": "php-mime-mail-parser/php-mime-mail-parser",
"type": "library",
- "description": "A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).",
+ "description": "A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).",
"keywords": ["mime", "mail", "mailparse", "MimeMailParser", "parser", "php"],
"homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
"license": "MIT",
@@ -42,14 +42,13 @@
"url":"https://github.com/php-mime-mail-parser/php-mime-mail-parser.git"
},
"require": {
- "php": "^7.1",
+ "php": "^7.2|^8.0",
"ext-mailparse": "*"
},
"require-dev": {
- "phpunit/phpunit": "^7.0",
- "phpunit/php-token-stream": "^3.0",
- "php-coveralls/php-coveralls": "^2.1",
- "squizlabs/php_codesniffer": "^3.4"
+ "phpunit/phpunit": "^8.0",
+ "php-coveralls/php-coveralls": "^2.2",
+ "squizlabs/php_codesniffer": "^3.5"
},
"replace": {
"exorus/php-mime-mail-parser": "*",
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/README.md
index d9cbbaa..fa27d2f 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/README.md
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/README.md
@@ -1,46 +1,45 @@
![PHPMailer](https://raw.github.com/PHPMailer/PHPMailer/master/examples/images/phpmailer.png)
-# PHPMailer - A full-featured email creation and transfer class for PHP
+# PHPMailer – A full-featured email creation and transfer class for PHP
-Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.svg)](https://travis-ci.org/PHPMailer/PHPMailer)
-[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/badges/quality-score.png?s=3758e21d279becdf847a557a56a3ed16dfec9d5d)](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/)
-[![Code Coverage](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/badges/coverage.png?s=3fe6ca5fe8cd2cdf96285756e42932f7ca256962)](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/)
+[![Test status](https://github.com/PHPMailer/PHPMailer/workflows/Tests/badge.svg)](https://github.com/PHPMailer/PHPMailer/actions) [![Latest Stable Version](https://poser.pugx.org/phpmailer/phpmailer/v/stable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![Total Downloads](https://poser.pugx.org/phpmailer/phpmailer/downloads)](https://packagist.org/packages/phpmailer/phpmailer) [![License](https://poser.pugx.org/phpmailer/phpmailer/license.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![API Docs](https://github.com/phpmailer/phpmailer/workflows/Docs/badge.svg)](https://phpmailer.github.io/PHPMailer/)
-[![Latest Stable Version](https://poser.pugx.org/phpmailer/phpmailer/v/stable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![Total Downloads](https://poser.pugx.org/phpmailer/phpmailer/downloads)](https://packagist.org/packages/phpmailer/phpmailer) [![Latest Unstable Version](https://poser.pugx.org/phpmailer/phpmailer/v/unstable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![License](https://poser.pugx.org/phpmailer/phpmailer/license.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![API Docs](https://github.com/phpmailer/phpmailer/workflows/Docs/badge.svg)](http://phpmailer.github.io/PHPMailer/)
-
-## Class Features
+## Features
- Probably the world's most popular code for sending email from PHP!
- Used by many open-source projects: WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla! and many more
-- Integrated SMTP support - send without a local mail server
+- Integrated SMTP support – send without a local mail server
- Send emails with multiple To, CC, BCC and Reply-to addresses
- Multipart/alternative emails for mail clients that do not read HTML email
- Add attachments, including inline
- Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings
-- SMTP authentication with LOGIN, PLAIN, CRAM-MD5, and XOAUTH2 mechanisms over SSL and SMTP+STARTTLS transports
+- SMTP authentication with LOGIN, PLAIN, CRAM-MD5, and XOAUTH2 mechanisms over SMTPS and SMTP+STARTTLS transports
- Validates email addresses automatically
-- Protect against header injection attacks
+- Protects against header injection attacks
- Error messages in over 50 languages!
- DKIM and S/MIME signing support
-- Compatible with PHP 5.5 and later
+- Compatible with PHP 5.5 and later, including PHP 8.0
- Namespaced to prevent name clashes
- Much more!
## Why you might need it
-Many PHP developers need to send email from their code. The only PHP function that supports this is [`mail()`](https://www.php.net/manual/en/function.mail.php). However, it does not provide any assistance for making use of popular features such as encryption, authentication, HTML messages, and attachments.
+Many PHP developers need to send email from their code. The only PHP function that supports this directly is [`mail()`](https://www.php.net/manual/en/function.mail.php). However, it does not provide any assistance for making use of popular features such as encryption, authentication, HTML messages, and attachments.
-Formatting email correctly is surprisingly difficult. There are myriad overlapping RFCs, requiring tight adherence to horribly complicated formatting and encoding rules – the vast majority of code that you'll find online that uses the `mail()` function directly is just plain wrong!
-*Please* don't be tempted to do it yourself – if you don't use PHPMailer, there are many other excellent libraries that you should look at before rolling your own. Try [SwiftMailer](https://swiftmailer.symfony.com/), [Zend/Mail](https://zendframework.github.io/zend-mail/), [ZetaComponents](https://github.com/zetacomponents/Mail) etc.
+Formatting email correctly is surprisingly difficult. There are myriad overlapping (and conflicting) standards, requiring tight adherence to horribly complicated formatting and encoding rules – the vast majority of code that you'll find online that uses the `mail()` function directly is just plain wrong, if not unsafe!
-The PHP `mail()` function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD, and macOS platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP implementation allows email sending on Windows platforms without a local mail server.
+The PHP `mail()` function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD, and macOS platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP client allows email sending on all platforms without needing a local mail server. Be aware though, that the `mail()` function should be avoided when possible; it's both faster and [safer](https://exploitbox.io/paper/Pwning-PHP-Mail-Function-For-Fun-And-RCE.html) to use SMTP to localhost.
+
+*Please* don't be tempted to do it yourself – if you don't use PHPMailer, there are many other excellent libraries that
+you should look at before rolling your own. Try [SwiftMailer](https://swiftmailer.symfony.com/)
+, [Laminas/Mail](https://docs.laminas.dev/laminas-mail/), [ZetaComponents](https://github.com/zetacomponents/Mail) etc.
## License
-This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lgpl-2.1.html) license, along with the [GPL Cooperation Commitment](https://gplcc.github.io/gplcc/). Please read LICENSE for information on the software availability and distribution.
+This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lgpl-2.1.html) license, along with the [GPL Cooperation Commitment](https://gplcc.github.io/gplcc/). Please read [LICENSE](https://github.com/PHPMailer/PHPMailer/blob/master/LICENSE) for information on the software availability and distribution.
## Installation & loading
PHPMailer is available on [Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), and installation via [Composer](https://getcomposer.org) is the recommended way to install PHPMailer. Just add this line to your `composer.json` file:
```json
-"phpmailer/phpmailer": "~6.1"
+"phpmailer/phpmailer": "^6.2"
```
or run
@@ -53,7 +52,8 @@
If you want to use the Gmail XOAUTH2 authentication class, you will also need to add a dependency on the `league/oauth2-client` package in your `composer.json`.
-Alternatively, if you're not using Composer, copy the contents of the PHPMailer folder into one of the `include_path` directories specified in your PHP configuration and load each class file manually:
+Alternatively, if you're not using Composer, you
+can [download PHPMailer as a zip file](https://github.com/PHPMailer/PHPMailer/archive/master.zip), (note that docs and examples are not included in the zip file), then copy the contents of the PHPMailer folder into one of the `include_path` directories specified in your PHP configuration and load each class file manually:
```php
<?php
@@ -65,60 +65,58 @@
require 'path/to/PHPMailer/src/SMTP.php';
```
-If you're not using the `SMTP` class explicitly (you're probably not), you don't need a `use` line for the SMTP class.
-
-If you don't speak git or just want a tarball, click the 'zip' button on the right of the project page in GitHub, though note that docs and examples are not included in the tarball.
+If you're not using the `SMTP` class explicitly (you're probably not), you don't need a `use` line for the SMTP class. Even if you're not using exceptions, you do still need to load the `Exception` class as it is used internally.
## Legacy versions
-PHPMailer 5.2 (which is compatible with PHP 5.0 - 7.0) is no longer being supported, even for security updates. You will find the latest version of 5.2 in the [5.2-stable branch](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable). If you're using PHP 5.5 or later (which you should be), switch to the 6.x releases.
+PHPMailer 5.2 (which is compatible with PHP 5.0 — 7.0) is no longer supported, even for security updates. You will find the latest version of 5.2 in the [5.2-stable branch](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable). If you're using PHP 5.5 or later (which you should be), switch to the 6.x releases.
### Upgrading from 5.2
The biggest changes are that source files are now in the `src/` folder, and PHPMailer now declares the namespace `PHPMailer\PHPMailer`. This has several important effects – [read the upgrade guide](https://github.com/PHPMailer/PHPMailer/tree/master/UPGRADING.md) for more details.
### Minimal installation
-While installing the entire package manually or with Composer is simple, convenient, and reliable, you may want to include only vital files in your project. At the very least you will need [src/PHPMailer.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/PHPMailer.php). If you're using SMTP, you'll need [src/SMTP.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/SMTP.php), and if you're using POP-before SMTP, you'll need [src/POP3.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/POP3.php). You can skip the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder if you're not showing errors to users and can make do with English-only errors. If you're using XOAUTH2 you will need [src/OAuth.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/OAuth.php) as well as the Composer dependencies for the services you wish to authenticate with. Really, it's much easier to use Composer!
+While installing the entire package manually or with Composer is simple, convenient, and reliable, you may want to include only vital files in your project. At the very least you will need [src/PHPMailer.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/PHPMailer.php). If you're using SMTP, you'll need [src/SMTP.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/SMTP.php), and if you're using POP-before SMTP (*very* unlikely!), you'll need [src/POP3.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/POP3.php). You can skip the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder if you're not showing errors to users and can make do with English-only errors. If you're using XOAUTH2 you will need [src/OAuth.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/OAuth.php) as well as the Composer dependencies for the services you wish to authenticate with. Really, it's much easier to use Composer!
## A Simple Example
```php
<?php
-// Import PHPMailer classes into the global namespace
-// These must be at the top of your script, not inside a function
+//Import PHPMailer classes into the global namespace
+//These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
-// Load Composer's autoloader
+//Load Composer's autoloader
require 'vendor/autoload.php';
-// Instantiation and passing `true` enables exceptions
+//Instantiation and passing `true` enables exceptions
$mail = new PHPMailer(true);
try {
//Server settings
- $mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
- $mail->isSMTP(); // Send using SMTP
- $mail->Host = 'smtp1.example.com'; // Set the SMTP server to send through
- $mail->SMTPAuth = true; // Enable SMTP authentication
- $mail->Username = 'user@example.com'; // SMTP username
- $mail->Password = 'secret'; // SMTP password
- $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
- $mail->Port = 587; // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
+ $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output
+ $mail->isSMTP(); //Send using SMTP
+ $mail->Host = 'smtp.example.com'; //Set the SMTP server to send through
+ $mail->SMTPAuth = true; //Enable SMTP authentication
+ $mail->Username = 'user@example.com'; //SMTP username
+ $mail->Password = 'secret'; //SMTP password
+ $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; //Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
+ $mail->Port = 587; //TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
//Recipients
$mail->setFrom('from@example.com', 'Mailer');
- $mail->addAddress('joe@example.net', 'Joe User'); // Add a recipient
- $mail->addAddress('ellen@example.com'); // Name is optional
+ $mail->addAddress('joe@example.net', 'Joe User'); //Add a recipient
+ $mail->addAddress('ellen@example.com'); //Name is optional
$mail->addReplyTo('info@example.com', 'Information');
$mail->addCC('cc@example.com');
$mail->addBCC('bcc@example.com');
- // Attachments
- $mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
- $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
+ //Attachments
+ $mail->addAttachment('/var/tmp/file.tar.gz'); //Add attachments
+ $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); //Optional name
- // Content
- $mail->isHTML(true); // Set email format to HTML
+ //Content
+ $mail->isHTML(true); //Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
@@ -130,7 +128,7 @@
}
```
-You'll find plenty more to play with in the [examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) folder.
+You'll find plenty to play with in the [examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) folder, which covers many common scenarios including sending through gmail, building contact forms, sending to mailing lists, and more.
If you are re-using the instance (e.g. when sending to a mailing list), you may need to clear the recipient list to avoid sending duplicate messages. See [the mailing list example](https://github.com/PHPMailer/PHPMailer/blob/master/examples/mailing_list.phps) for further guidance.
@@ -140,43 +138,43 @@
PHPMailer defaults to English, but in the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder you'll find many translations for PHPMailer error messages that you may encounter. Their filenames contain [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code for the translations, for example `fr` for French. To specify a language, you need to tell PHPMailer which one to use, like this:
```php
-// To load the French version
+//To load the French version
$mail->setLanguage('fr', '/optional/path/to/language/directory/');
```
-We welcome corrections and new languages - if you're looking for corrections to do, run the [PHPMailerLangTest.php](https://github.com/PHPMailer/PHPMailer/tree/master/test/PHPMailerLangTest.php) script in the tests folder and it will show any missing translations.
+We welcome corrections and new languages – if you're looking for corrections, run the [PHPMailerLangTest.php](https://github.com/PHPMailer/PHPMailer/tree/master/test/PHPMailerLangTest.php) script in the tests folder and it will show any missing translations.
## Documentation
-Start reading at the [GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki). If you're having trouble, this should be the first place you look as it's the most frequently updated.
+Start reading at the [GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki). If you're having trouble, head for [the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting) as it's frequently updated.
Examples of how to use PHPMailer for common scenarios can be found in the [examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) folder. If you're looking for a good starting point, we recommend you start with [the Gmail example](https://github.com/PHPMailer/PHPMailer/tree/master/examples/gmail.phps).
-Note that in order to reduce PHPMailer's deployed code footprint, the examples are no longer included if you load PHPMailer via Composer or via [GitHub's zip file download](https://github.com/PHPMailer/PHPMailer/archive/master.zip), so you'll need to either clone the git repository or use the above links to get to the examples directly.
+To reduce PHPMailer's deployed code footprint, examples are not included if you load PHPMailer via Composer or via [GitHub's zip file download](https://github.com/PHPMailer/PHPMailer/archive/master.zip), so you'll need to either clone the git repository or use the above links to get to the examples directly.
-Complete generated API documentation is [available online](http://phpmailer.github.io/PHPMailer/).
+Complete generated API documentation is [available online](https://phpmailer.github.io/PHPMailer/).
-You can generate complete API-level documentation by running `phpdoc` in the top-level folder, and documentation will appear in the `docs` folder, though you'll need to have [PHPDocumentor](http://www.phpdoc.org) installed. You may find [the unit tests](https://github.com/PHPMailer/PHPMailer/blob/master/test/PHPMailerTest.php) a good source of how to do various operations such as encryption.
+You can generate complete API-level documentation by running `phpdoc` in the top-level folder, and documentation will appear in the `docs` folder, though you'll need to have [PHPDocumentor](http://www.phpdoc.org) installed. You may find [the unit tests](https://github.com/PHPMailer/PHPMailer/blob/master/test/PHPMailerTest.php) a good reference for how to do various operations such as encryption.
If the documentation doesn't cover what you need, search the [many questions on Stack Overflow](http://stackoverflow.com/questions/tagged/phpmailer), and before you ask a question about "SMTP Error: Could not connect to SMTP host.", [read the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting).
## Tests
-There is a PHPUnit test script in the [test](https://github.com/PHPMailer/PHPMailer/tree/master/test/) folder. PHPMailer uses PHPUnit 4.8 - we would use 5.x but we need to run on PHP 5.5.
+[PHPMailer tests](https://github.com/PHPMailer/PHPMailer/tree/master/test/) use PHPUnit 9, with [a polyfill](https://github.com/Yoast/PHPUnit-Polyfills) to let 9-style tests run on older PHPUnit and PHP versions.
-Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.svg)](https://travis-ci.org/PHPMailer/PHPMailer)
+[![Test status](https://github.com/PHPMailer/PHPMailer/workflows/Tests/badge.svg)](https://github.com/PHPMailer/PHPMailer/actions)
If this isn't passing, is there something you can do to help?
## Security
Please disclose any vulnerabilities found responsibly – report security issues to the maintainers privately.
-See [SECURITY](https://github.com/PHPMailer/PHPMailer/tree/master/SECURITY.md) for details on security issues.
+See [SECURITY](https://github.com/PHPMailer/PHPMailer/tree/master/SECURITY.md) and [PHPMailer's security advisories on GitHub](https://github.com/PHPMailer/PHPMailer/security).
## Contributing
Please submit bug reports, suggestions and pull requests to the [GitHub issue tracker](https://github.com/PHPMailer/PHPMailer/issues).
We're particularly interested in fixing edge-cases, expanding test coverage and updating translations.
-If you found a mistake in the docs, or want to add something, go ahead and amend the wiki - anyone can edit it.
+If you found a mistake in the docs, or want to add something, go ahead and amend the wiki – anyone can edit it.
If you have git clones from prior to the move to the PHPMailer GitHub organisation, you'll need to update any remote URLs referencing the old GitHub location with a command like this from within your clone:
@@ -187,27 +185,36 @@
Please *don't* use the SourceForge or Google Code projects any more; they are obsolete and no longer maintained.
## Sponsorship
-Development time and resources for PHPMailer are provided by [Smartmessages.net](https://info.smartmessages.net/), a powerful email marketing system.
+Development time and resources for PHPMailer are provided by [Smartmessages.net](https://info.smartmessages.net/), the world's only privacy-first email marketing system.
-<a href="https://info.smartmessages.net/"><img src="https://www.smartmessages.net/img/smartmessages-logo.svg" width="250" height="28" alt="Smartmessages email marketing"></a>
+<a href="https://info.smartmessages.net/"><img src="https://www.smartmessages.net/img/smartmessages-logo.svg" width="550" alt="Smartmessages.net privacy-first email marketing logo"></a>
-Other contributions are gladly received, whether in beer 🍺, T-shirts 👕, Amazon wishlist raids, or cold, hard cash 💰. If you'd like to donate to say "thank you" to maintainers or contributors, please contact them through individual profile pages via [the contributors page](https://github.com/PHPMailer/PHPMailer/graphs/contributors).
+Donations are very welcome, whether in beer 🍺, T-shirts 👕, or cold, hard cash 💰. Sponsorship through GitHub is a simple and convenient way to say "thank you" to PHPMailer's maintainers and contributors – just click the "Sponsor" button [on the project page](https://github.com/PHPMailer/PHPMailer). If your company uses PHPMailer, consider taking part in Tidelift's enterprise support programme.
+
+## PHPMailer For Enterprise
+
+Available as part of the Tidelift Subscription.
+
+The maintainers of PHPMailer and thousands of other packages are working with Tidelift to deliver commercial
+support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and
+improve code health, while paying the maintainers of the exact packages you
+use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-phpmailer-phpmailer?utm_source=packagist-phpmailer-phpmailer&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
## Changelog
See [changelog](changelog.md).
## History
- PHPMailer was originally written in 2001 by Brent R. Matzelle as a [SourceForge project](http://sourceforge.net/projects/phpmailer/).
-- Marcus Bointon (coolbru on SF) and Andy Prevost (codeworxtech) took over the project in 2004.
+- [Marcus Bointon](https://github.com/Synchro) (`coolbru` on SF) and Andy Prevost (`codeworxtech`) took over the project in 2004.
- Became an Apache incubator project on Google Code in 2010, managed by Jim Jagielski.
-- Marcus created his fork on [GitHub](https://github.com/Synchro/PHPMailer) in 2008.
+- Marcus created [his fork on GitHub](https://github.com/Synchro/PHPMailer) in 2008.
- Jim and Marcus decide to join forces and use GitHub as the canonical and official repo for PHPMailer in 2013.
-- PHPMailer moves to the [PHPMailer organisation](https://github.com/PHPMailer) on GitHub in 2013.
+- PHPMailer moves to [the PHPMailer organisation](https://github.com/PHPMailer) on GitHub in 2013.
### What's changed since moving from SourceForge?
- Official successor to the SourceForge and Google Code projects.
- Test suite.
-- Continuous integration with Travis-CI.
+- Continuous integration with Github Actions.
- Composer support.
- Public development.
- Additional languages and language strings.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/SECURITY.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/SECURITY.md
index fc3e61c..035a87f 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/SECURITY.md
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/SECURITY.md
@@ -1,6 +1,13 @@
# Security notices relating to PHPMailer
-Please disclose any vulnerabilities found responsibly - report any security problems found to the maintainers privately.
+Please disclose any security issues or vulnerabilities found through [Tidelift's coordinated disclosure system](https://tidelift.com/security) or to the maintainers privately.
+
+PHPMailer 6.4.1 and earlier contain a vulnerability that can result in untrusted code being called (if such code is injected into the host project's scope by other means). If the `$patternselect` parameter to `validateAddress()` is set to `'php'` (the default, defined by `PHPMailer::$validator`), and the global namespace contains a function called `php`, it will be called in preference to the built-in validator of the same name. Mitigated in PHPMailer 6.5.0 by denying the use of simple strings as validator function names. Recorded as [CVE-2021-3603](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-3603). Reported by [Vikrant Singh Chauhan](mailto:vi@hackberry.xyz) via [huntr.dev](https://www.huntr.dev/).
+
+PHPMailer versions 6.4.1 and earlier contain a possible remote code execution vulnerability through the `$lang_path` parameter of the `setLanguage()` method. If the `$lang_path` parameter is passed unfiltered from user input, it can be set to [a UNC path](https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats#unc-paths), and if an attacker is also able to persuade the server to load a file from that UNC path, a script file under their control may be executed. This vulnerability only applies to systems that resolve UNC paths, typically only Microsoft Windows.
+PHPMailer 6.5.0 mitigates this by no longer treating translation files as PHP code, but by parsing their text content directly. This approach avoids the possibility of executing unknown code while retaining backward compatibility. This isn't ideal, so the current translation format is deprecated and will be replaced in the next major release. Recorded as [CVE-2021-34551](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-34551). Reported by [Jilin Diting Information Technology Co., Ltd](https://listensec.com) via Tidelift.
+
+PHPMailer versions between 6.1.8 and 6.4.0 contain a regression of the earlier CVE-2018-19296 object injection vulnerability as a result of [a fix for Windows UNC paths in 6.1.8](https://github.com/PHPMailer/PHPMailer/commit/e2e07a355ee8ff36aba21d0242c5950c56e4c6f9). Recorded as [CVE-2020-36326](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-36326). Reported by Fariskhi Vidyan via Tidelift. 6.4.1 fixes this issue, and also enforces stricter checks for URL schemes in local path contexts.
PHPMailer versions 6.1.5 and earlier contain an output escaping bug that occurs in `Content-Type` and `Content-Disposition` when filenames passed into `addAttachment` and other methods that accept attachment names contain double quote characters, in contravention of RFC822 3.4.1. No specific vulnerability has been found relating to this, but it could allow file attachments to bypass attachment filters that are based on matching filename extensions. Recorded as [CVE-2020-13625](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-13625). Reported by Elar Lang of Clarified Security.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/VERSION b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/VERSION
index 4ac4fde..4be2c72 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/VERSION
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/VERSION
@@ -1 +1 @@
-6.2.0
\ No newline at end of file
+6.5.0
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/composer.json
index 7388bd9..58393b2 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/composer.json
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/composer.json
@@ -40,7 +40,7 @@
"yoast/phpunit-polyfills": "^0.2.0"
},
"suggest": {
- "ext-mbstring": "Needed to send email in multibyte encoding charset",
+ "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
"psr/log": "For optional PSR-3 debug logging",
@@ -57,5 +57,9 @@
"PHPMailer\\Test\\": "test/"
}
},
- "license": "LGPL-2.1-only"
+ "license": "LGPL-2.1-only",
+ "scripts": {
+ "check": "./vendor/bin/phpcs",
+ "test": "./vendor/bin/phpunit"
+ }
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/get_oauth_token.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/get_oauth_token.php
index 560d364..befdc34 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/get_oauth_token.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/get_oauth_token.php
@@ -38,20 +38,20 @@
* Plenty to choose from here:
* @see http://oauth2-client.thephpleague.com/providers/thirdparty/
*/
-// @see https://github.com/thephpleague/oauth2-google
+//@see https://github.com/thephpleague/oauth2-google
use League\OAuth2\Client\Provider\Google;
-// @see https://packagist.org/packages/hayageek/oauth2-yahoo
+//@see https://packagist.org/packages/hayageek/oauth2-yahoo
use Hayageek\OAuth2\Client\Provider\Yahoo;
-// @see https://github.com/stevenmaguire/oauth2-microsoft
+//@see https://github.com/stevenmaguire/oauth2-microsoft
use Stevenmaguire\OAuth2\Client\Provider\Microsoft;
if (!isset($_GET['code']) && !isset($_GET['provider'])) {
?>
<html>
-<body>Select Provider:<br/>
-<a href='?provider=Google'>Google</a><br/>
-<a href='?provider=Yahoo'>Yahoo</a><br/>
-<a href='?provider=Microsoft'>Microsoft/Outlook/Hotmail/Live/Office365</a><br/>
+<body>Select Provider:<br>
+<a href='?provider=Google'>Google</a><br>
+<a href='?provider=Yahoo'>Yahoo</a><br>
+<a href='?provider=Microsoft'>Microsoft/Outlook/Hotmail/Live/Office365</a><br>
</body>
</html>
<?php
@@ -121,26 +121,26 @@
}
if (!isset($_GET['code'])) {
- // If we don't have an authorization code then get one
+ //If we don't have an authorization code then get one
$authUrl = $provider->getAuthorizationUrl($options);
$_SESSION['oauth2state'] = $provider->getState();
header('Location: ' . $authUrl);
exit;
-// Check given state against previously stored one to mitigate CSRF attack
+ //Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
unset($_SESSION['oauth2state']);
unset($_SESSION['provider']);
exit('Invalid state');
} else {
unset($_SESSION['provider']);
- // Try to get an access token (using the authorization code grant)
+ //Try to get an access token (using the authorization code grant)
$token = $provider->getAccessToken(
'authorization_code',
[
'code' => $_GET['code']
]
);
- // Use this to interact with an API on the users behalf
- // Use this to get a new access token if the old one expires
+ //Use this to interact with an API on the users behalf
+ //Use this to get a new access token if the old one expires
echo 'Refresh Token: ', $token->getRefreshToken();
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-ar.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-ar.php
index 8ab485c..f795580 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-ar.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-ar.php
@@ -19,8 +19,7 @@
$PHPMAILER_LANG['invalid_address'] = 'الإرسال غير ممكن لأن عنوان البريد الإلكتروني غير صالح: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' برنامج الإرسال غير مدعوم.';
$PHPMAILER_LANG['provide_address'] = 'يجب توفير عنوان البريد الإلكتروني لمستلم واحد على الأقل.';
-$PHPMAILER_LANG['recipients_failed'] = 'خطأ SMTP: الأخطاء التالية ' .
- 'فشل في الارسال لكل من : ';
+$PHPMAILER_LANG['recipients_failed'] = 'خطأ SMTP: الأخطاء التالية فشل في الارسال لكل من : ';
$PHPMAILER_LANG['signing'] = 'خطأ في التوقيع: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() غير ممكن.';
$PHPMAILER_LANG['smtp_error'] = 'خطأ على مستوى الخادم SMTP: ';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-cs.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-cs.php
index 55bdd9c..e770a1a 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-cs.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-cs.php
@@ -16,6 +16,8 @@
$PHPMAILER_LANG['from_failed'] = 'Následující adresa odesílatele je nesprávná: ';
$PHPMAILER_LANG['instantiate'] = 'Nelze vytvořit instanci emailové funkce.';
$PHPMAILER_LANG['invalid_address'] = 'Neplatná adresa: ';
+$PHPMAILER_LANG['invalid_hostentry'] = 'Záznam hostitele je nesprávný: ';
+$PHPMAILER_LANG['invalid_host'] = 'Hostitel je nesprávný: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer není podporován.';
$PHPMAILER_LANG['provide_address'] = 'Musíte zadat alespoň jednu emailovou adresu příjemce.';
$PHPMAILER_LANG['recipients_failed'] = 'Chyba SMTP: Následující adresy příjemců nejsou správně: ';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-sk.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-sk.php
index a1cfb28..028f5bc 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-sk.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-sk.php
@@ -18,6 +18,8 @@
$PHPMAILER_LANG['from_failed'] = 'Následujúca adresa From je nesprávna: ';
$PHPMAILER_LANG['instantiate'] = 'Nedá sa vytvoriť inštancia emailovej funkcie.';
$PHPMAILER_LANG['invalid_address'] = 'Neodoslané, emailová adresa je nesprávna: ';
+$PHPMAILER_LANG['invalid_hostentry'] = 'Záznam hostiteľa je nesprávny: ';
+$PHPMAILER_LANG['invalid_host'] = 'Hostiteľ je nesprávny: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' emailový klient nieje podporovaný.';
$PHPMAILER_LANG['provide_address'] = 'Musíte zadať aspoň jednu emailovú adresu príjemcu.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: Adresy príjemcov niesu správne ';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-sr_latn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-sr_latn.php
new file mode 100644
index 0000000..6213832
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-sr_latn.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * Serbian PHPMailer language file: refer to English translation for definitive list
+ * @package PHPMailer
+ * @author Александар Јевремовић <ajevremovic@gmail.com>
+ * @author Miloš Milanović <mmilanovic016@gmail.com>
+ */
+
+$PHPMAILER_LANG['authenticate'] = 'SMTP greška: autentifikacija nije uspela.';
+$PHPMAILER_LANG['connect_host'] = 'SMTP greška: povezivanje sa SMTP serverom nije uspelo.';
+$PHPMAILER_LANG['data_not_accepted'] = 'SMTP greška: podaci nisu prihvaćeni.';
+$PHPMAILER_LANG['empty_message'] = 'Sadržaj poruke je prazan.';
+$PHPMAILER_LANG['encoding'] = 'Nepoznato kodiranje: ';
+$PHPMAILER_LANG['execute'] = 'Nije moguće izvršiti naredbu: ';
+$PHPMAILER_LANG['file_access'] = 'Nije moguće pristupiti datoteci: ';
+$PHPMAILER_LANG['file_open'] = 'Nije moguće otvoriti datoteku: ';
+$PHPMAILER_LANG['from_failed'] = 'SMTP greška: slanje sa sledećih adresa nije uspelo: ';
+$PHPMAILER_LANG['recipients_failed'] = 'SMTP greška: slanje na sledeće adrese nije uspelo: ';
+$PHPMAILER_LANG['instantiate'] = 'Nije moguće pokrenuti mail funkciju.';
+$PHPMAILER_LANG['invalid_address'] = 'Poruka nije poslata. Neispravna adresa: ';
+$PHPMAILER_LANG['mailer_not_supported'] = ' majler nije podržan.';
+$PHPMAILER_LANG['provide_address'] = 'Definišite bar jednu adresu primaoca.';
+$PHPMAILER_LANG['signing'] = 'Greška prilikom prijave: ';
+$PHPMAILER_LANG['smtp_connect_failed'] = 'Povezivanje sa SMTP serverom nije uspelo.';
+$PHPMAILER_LANG['smtp_error'] = 'Greška SMTP servera: ';
+$PHPMAILER_LANG['variable_set'] = 'Nije moguće zadati niti resetovati promenljivu: ';
+$PHPMAILER_LANG['extension_missing'] = 'Nedostaje proširenje: ';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-uk.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-uk.php
index 9fa60cf..3dea055 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-uk.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/language/phpmailer.lang-uk.php
@@ -16,11 +16,11 @@
$PHPMAILER_LANG['file_open'] = 'Помилка файлової системи: не вдається відкрити файл: ';
$PHPMAILER_LANG['from_failed'] = 'Невірна адреса відправника: ';
$PHPMAILER_LANG['instantiate'] = 'Неможливо запустити функцію mail().';
-$PHPMAILER_LANG['provide_address'] = 'Будь-ласка, введіть хоча б одну email-адресу отримувача.';
+$PHPMAILER_LANG['provide_address'] = 'Будь ласка, введіть хоча б одну email-адресу отримувача.';
$PHPMAILER_LANG['mailer_not_supported'] = ' - поштовий сервер не підтримується.';
$PHPMAILER_LANG['recipients_failed'] = 'Помилка SMTP: не вдалося відправлення для таких отримувачів: ';
$PHPMAILER_LANG['empty_message'] = 'Пусте повідомлення';
-$PHPMAILER_LANG['invalid_address'] = 'Не відправлено через невірний формат email-адреси: ';
+$PHPMAILER_LANG['invalid_address'] = 'Не відправлено через неправильний формат email-адреси: ';
$PHPMAILER_LANG['signing'] = 'Помилка підпису: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'Помилка з\'єднання з SMTP-сервером';
$PHPMAILER_LANG['smtp_error'] = 'Помилка SMTP-сервера: ';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/phpunit.xml.dist b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/phpunit.xml.dist
new file mode 100644
index 0000000..c68df96
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/phpunit.xml.dist
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd"
+ backupGlobals="true"
+ bootstrap="vendor/autoload.php"
+ verbose="true"
+ colors="true"
+ forceCoversAnnotation="false"
+ >
+ <testsuites>
+ <testsuite name="PHPMailerTests">
+ <directory>./test/</directory>
+ </testsuite>
+ </testsuites>
+ <listeners>
+ <listener class="PHPMailer\Test\DebugLogTestListener" />
+ </listeners>
+ <groups>
+ <exclude>
+ <group>languages</group>
+ <group>pop3</group>
+ </exclude>
+ </groups>
+ <filter>
+ <whitelist addUncoveredFilesFromWhitelist="true">
+ <directory suffix=".php">./src</directory>
+ </whitelist>
+ </filter>
+ <logging>
+ <log type="coverage-text" target="php://stdout" showUncoveredFiles="true"/>
+ <log type="coverage-clover" target="build/logs/clover.xml"/>
+ <log type="junit" target="build/logs/junit.xml"/>
+ </logging>
+</phpunit>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/OAuth.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/OAuth.php
index 07fde4c..c93d0be 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/OAuth.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/OAuth.php
@@ -123,7 +123,7 @@
*/
public function getOauth64()
{
- // Get a new token if it's not available or has expired
+ //Get a new token if it's not available or has expired
if (null === $this->oauthToken || $this->oauthToken->hasExpired()) {
$this->oauthToken = $this->getToken();
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/PHPMailer.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/PHPMailer.php
index c8fc1a8..eb4b742 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/PHPMailer.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/PHPMailer.php
@@ -428,9 +428,11 @@
public $Debugoutput = 'echo';
/**
- * Whether to keep SMTP connection open after each message.
- * If this is set to true then to close the connection
- * requires an explicit call to smtpClose().
+ * Whether to keep the SMTP connection open after each message.
+ * If this is set to true then the connection will remain open after a send,
+ * and closing the connection will require an explicit call to smtpClose().
+ * It's a good idea to use this if you are sending multiple messages as it reduces overhead.
+ * See the mailing list example for how to use it.
*
* @var bool
*/
@@ -748,7 +750,7 @@
*
* @var string
*/
- const VERSION = '6.2.0';
+ const VERSION = '6.5.0';
/**
* Error severity: message only, continue processing.
@@ -862,18 +864,25 @@
$subject = $this->encodeHeader($this->secureHeader($subject));
}
//Calling mail() with null params breaks
+ $this->edebug('Sending with mail()');
+ $this->edebug('Sendmail path: ' . ini_get('sendmail_path'));
+ $this->edebug("Envelope sender: {$this->Sender}");
+ $this->edebug("To: {$to}");
+ $this->edebug("Subject: {$subject}");
+ $this->edebug("Headers: {$header}");
if (!$this->UseSendmailOptions || null === $params) {
$result = @mail($to, $subject, $body, $header);
} else {
+ $this->edebug("Additional params: {$params}");
$result = @mail($to, $subject, $body, $header, $params);
}
-
+ $this->edebug('Result: ' . ($result ? 'true' : 'false'));
return $result;
}
/**
- * Output debugging info via user-defined method.
- * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
+ * Output debugging info via a user-defined method.
+ * Only generates output if debug output is enabled.
*
* @see PHPMailer::$Debugoutput
* @see PHPMailer::$SMTPDebug
@@ -1070,7 +1079,7 @@
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
$pos = strrpos($address, '@');
if (false === $pos) {
- // At-sign is missing.
+ //At-sign is missing.
$error_message = sprintf(
'%s (%s): %s',
$this->lang('invalid_address'),
@@ -1086,7 +1095,7 @@
return false;
}
$params = [$kind, $address, $name];
- // Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
+ //Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
if (static::idnSupported() && $this->has8bitChars(substr($address, ++$pos))) {
if ('Reply-To' !== $kind) {
if (!array_key_exists($address, $this->RecipientsQueue)) {
@@ -1103,7 +1112,7 @@
return false;
}
- // Immediately add standard addresses without IDN.
+ //Immediately add standard addresses without IDN.
return call_user_func_array([$this, 'addAnAddress'], $params);
}
@@ -1191,6 +1200,15 @@
$address->mailbox . '@' . $address->host
)
) {
+ //Decode the name part if it's present and encoded
+ if (
+ property_exists($address, 'personal') &&
+ extension_loaded('mbstring') &&
+ preg_match('/^=\?.*\?=$/', $address->personal)
+ ) {
+ $address->personal = mb_decode_mimeheader($address->personal);
+ }
+
$addresses[] = [
'name' => (property_exists($address, 'personal') ? $address->personal : ''),
'address' => $address->mailbox . '@' . $address->host,
@@ -1214,9 +1232,15 @@
} else {
list($name, $email) = explode('<', $address);
$email = trim(str_replace('>', '', $email));
+ $name = trim($name);
if (static::validateAddress($email)) {
+ //If this name is encoded, decode it
+ if (preg_match('/^=\?.*\?=$/', $name)) {
+ $name = mb_decode_mimeheader($name);
+ }
$addresses[] = [
- 'name' => trim(str_replace(['"', "'"], '', $name)),
+ //Remove any surrounding quotes and spaces from the name
+ 'name' => trim($name, '\'" '),
'address' => $email,
];
}
@@ -1242,7 +1266,7 @@
{
$address = trim($address);
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
- // Don't validate now addresses with IDN. Will be done in send().
+ //Don't validate now addresses with IDN. Will be done in send().
$pos = strrpos($address, '@');
if (
(false === $pos)
@@ -1313,7 +1337,8 @@
if (null === $patternselect) {
$patternselect = static::$validator;
}
- if (is_callable($patternselect)) {
+ //Don't allow strings as callables, see SECURITY.md and CVE-2021-3603
+ if (is_callable($patternselect) && !is_string($patternselect)) {
return call_user_func($patternselect, $address);
}
//Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
@@ -1395,7 +1420,7 @@
*/
public function punyencodeAddress($address)
{
- // Verify we have required functions, CharSet, and at-sign.
+ //Verify we have required functions, CharSet, and at-sign.
$pos = strrpos($address, '@');
if (
!empty($this->CharSet) &&
@@ -1403,16 +1428,20 @@
static::idnSupported()
) {
$domain = substr($address, ++$pos);
- // Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
+ //Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
if ($this->has8bitChars($domain) && @mb_check_encoding($domain, $this->CharSet)) {
- $domain = mb_convert_encoding($domain, 'UTF-8', $this->CharSet);
+ //Convert the domain from whatever charset it's in to UTF-8
+ $domain = mb_convert_encoding($domain, self::CHARSET_UTF8, $this->CharSet);
//Ignore IDE complaints about this line - method signature changed in PHP 5.4
$errorcode = 0;
if (defined('INTL_IDNA_VARIANT_UTS46')) {
- $punycode = idn_to_ascii($domain, $errorcode, INTL_IDNA_VARIANT_UTS46);
+ //Use the current punycode standard (appeared in PHP 7.2)
+ $punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VARIANT_UTS46);
} elseif (defined('INTL_IDNA_VARIANT_2003')) {
- $punycode = idn_to_ascii($domain, $errorcode, INTL_IDNA_VARIANT_2003);
+ //Fall back to this old, deprecated/removed encoding
+ $punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VARIANT_2003);
} else {
+ //Fall back to a default we don't know about
$punycode = idn_to_ascii($domain, $errorcode);
}
if (false !== $punycode) {
@@ -1462,7 +1491,7 @@
{
if (
'smtp' === $this->Mailer
- || ('mail' === $this->Mailer && (PHP_VERSION_ID >= 80000 || stripos(PHP_OS, 'WIN') === 0))
+ || ('mail' === $this->Mailer && (\PHP_VERSION_ID >= 80000 || stripos(PHP_OS, 'WIN') === 0))
) {
//SMTP mandates RFC-compliant line endings
//and it's also used with mail() on Windows
@@ -1474,8 +1503,8 @@
//Check for buggy PHP versions that add a header with an incorrect line break
if (
'mail' === $this->Mailer
- && ((PHP_VERSION_ID >= 70000 && PHP_VERSION_ID < 70017)
- || (PHP_VERSION_ID >= 70100 && PHP_VERSION_ID < 70103))
+ && ((\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70017)
+ || (\PHP_VERSION_ID >= 70100 && \PHP_VERSION_ID < 70103))
&& ini_get('mail.add_x_header') === '1'
&& stripos(PHP_OS, 'WIN') === 0
) {
@@ -1488,10 +1517,10 @@
}
try {
- $this->error_count = 0; // Reset errors
+ $this->error_count = 0; //Reset errors
$this->mailHeader = '';
- // Dequeue recipient and Reply-To addresses with IDN
+ //Dequeue recipient and Reply-To addresses with IDN
foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
$params[1] = $this->punyencodeAddress($params[1]);
call_user_func_array([$this, 'addAnAddress'], $params);
@@ -1500,7 +1529,7 @@
throw new Exception($this->lang('provide_address'), self::STOP_CRITICAL);
}
- // Validate From, Sender, and ConfirmReadingTo addresses
+ //Validate From, Sender, and ConfirmReadingTo addresses
foreach (['From', 'Sender', 'ConfirmReadingTo'] as $address_kind) {
$this->$address_kind = trim($this->$address_kind);
if (empty($this->$address_kind)) {
@@ -1524,29 +1553,29 @@
}
}
- // Set whether the message is multipart/alternative
+ //Set whether the message is multipart/alternative
if ($this->alternativeExists()) {
$this->ContentType = static::CONTENT_TYPE_MULTIPART_ALTERNATIVE;
}
$this->setMessageType();
- // Refuse to send an empty message unless we are specifically allowing it
+ //Refuse to send an empty message unless we are specifically allowing it
if (!$this->AllowEmpty && empty($this->Body)) {
throw new Exception($this->lang('empty_message'), self::STOP_CRITICAL);
}
//Trim subject consistently
$this->Subject = trim($this->Subject);
- // Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
+ //Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
$this->MIMEHeader = '';
$this->MIMEBody = $this->createBody();
- // createBody may have added some headers, so retain them
+ //createBody may have added some headers, so retain them
$tempheaders = $this->MIMEHeader;
$this->MIMEHeader = $this->createHeader();
$this->MIMEHeader .= $tempheaders;
- // To capture the complete message when using mail(), create
- // an extra header list which createHeader() doesn't fold in
+ //To capture the complete message when using mail(), create
+ //an extra header list which createHeader() doesn't fold in
if ('mail' === $this->Mailer) {
if (count($this->to) > 0) {
$this->mailHeader .= $this->addrAppend('To', $this->to);
@@ -1559,7 +1588,7 @@
);
}
- // Sign with DKIM if enabled
+ //Sign with DKIM if enabled
if (
!empty($this->DKIM_domain)
&& !empty($this->DKIM_selector)
@@ -1600,7 +1629,7 @@
public function postSend()
{
try {
- // Choose the mailer and send through it
+ //Choose the mailer and send through it
switch ($this->Mailer) {
case 'sendmail':
case 'qmail':
@@ -1645,22 +1674,44 @@
*/
protected function sendmailSend($header, $body)
{
+ if ($this->Mailer === 'qmail') {
+ $this->edebug('Sending with qmail');
+ } else {
+ $this->edebug('Sending with sendmail');
+ }
$header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
-
- // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
- if (!empty($this->Sender) && self::isShellSafe($this->Sender)) {
- if ('qmail' === $this->Mailer) {
+ //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
+ //A space after `-f` is optional, but there is a long history of its presence
+ //causing problems, so we don't use one
+ //Exim docs: http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
+ //Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html
+ //Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html
+ //Example problem: https://www.drupal.org/node/1057954
+ if (empty($this->Sender) && !empty(ini_get('sendmail_from'))) {
+ //PHP config has a sender address we can use
+ $this->Sender = ini_get('sendmail_from');
+ }
+ //CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
+ if (!empty($this->Sender) && static::validateAddress($this->Sender) && self::isShellSafe($this->Sender)) {
+ if ($this->Mailer === 'qmail') {
$sendmailFmt = '%s -f%s';
} else {
$sendmailFmt = '%s -oi -f%s -t';
}
- } elseif ('qmail' === $this->Mailer) {
- $sendmailFmt = '%s';
} else {
+ //allow sendmail to choose a default envelope sender. It may
+ //seem preferable to force it to use the From header as with
+ //SMTP, but that introduces new problems (see
+ //<https://github.com/PHPMailer/PHPMailer/issues/2298>), and
+ //it has historically worked this way.
$sendmailFmt = '%s -oi -t';
}
$sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender);
+ $this->edebug('Sendmail path: ' . $this->Sendmail);
+ $this->edebug('Sendmail command: ' . $sendmail);
+ $this->edebug('Envelope sender: ' . $this->Sender);
+ $this->edebug("Headers: {$header}");
if ($this->SingleTo) {
foreach ($this->SingleToArray as $toAddr) {
@@ -1668,13 +1719,15 @@
if (!$mail) {
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
+ $this->edebug("To: {$toAddr}");
fwrite($mail, 'To: ' . $toAddr . "\n");
fwrite($mail, $header);
fwrite($mail, $body);
$result = pclose($mail);
+ $addrinfo = static::parseAddresses($toAddr);
$this->doCallback(
($result === 0),
- [$toAddr],
+ [[$addrinfo['address'], $addrinfo['name']]],
$this->cc,
$this->bcc,
$this->Subject,
@@ -1682,6 +1735,7 @@
$this->From,
[]
);
+ $this->edebug("Result: " . ($result === 0 ? 'true' : 'false'));
if (0 !== $result) {
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
@@ -1704,6 +1758,7 @@
$this->From,
[]
);
+ $this->edebug("Result: " . ($result === 0 ? 'true' : 'false'));
if (0 !== $result) {
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
@@ -1724,7 +1779,7 @@
*/
protected static function isShellSafe($string)
{
- // Future-proof
+ //Future-proof
if (
escapeshellcmd($string) !== $string
|| !in_array(escapeshellarg($string), ["'$string'", "\"$string\""])
@@ -1737,9 +1792,9 @@
for ($i = 0; $i < $length; ++$i) {
$c = $string[$i];
- // All other characters have a special meaning in at least one common shell, including = and +.
- // Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
- // Note that this does permit non-Latin alphanumeric characters based on the current locale.
+ //All other characters have a special meaning in at least one common shell, including = and +.
+ //Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
+ //Note that this does permit non-Latin alphanumeric characters based on the current locale.
if (!ctype_alnum($c) && strpos('@_-.', $c) === false) {
return false;
}
@@ -1759,7 +1814,8 @@
*/
protected static function isPermittedPath($path)
{
- return !preg_match('#^[a-z]+://#i', $path);
+ //Matches scheme definition from https://tools.ietf.org/html/rfc3986#section-3.1
+ return !preg_match('#^[a-z][a-z\d+.-]*://#i', $path);
}
/**
@@ -1771,12 +1827,15 @@
*/
protected static function fileIsAccessible($path)
{
+ if (!static::isPermittedPath($path)) {
+ return false;
+ }
$readable = file_exists($path);
//If not a UNC path (expected to start with \\), check read permission, see #2069
if (strpos($path, '\\\\') !== 0) {
$readable = $readable && is_readable($path);
}
- return static::isPermittedPath($path) && $readable;
+ return $readable;
}
/**
@@ -1809,11 +1868,15 @@
//Sendmail docs: http://www.sendmail.org/~ca/email/man/sendmail.html
//Qmail docs: http://www.qmail.org/man/man8/qmail-inject.html
//Example problem: https://www.drupal.org/node/1057954
- // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
- if (!empty($this->Sender) && static::validateAddress($this->Sender) && self::isShellSafe($this->Sender)) {
- $params = sprintf('-f%s', $this->Sender);
+ //CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
+ if (empty($this->Sender) && !empty(ini_get('sendmail_from'))) {
+ //PHP config has a sender address we can use
+ $this->Sender = ini_get('sendmail_from');
}
if (!empty($this->Sender) && static::validateAddress($this->Sender)) {
+ if (self::isShellSafe($this->Sender)) {
+ $params = sprintf('-f%s', $this->Sender);
+ }
$old_from = ini_get('sendmail_from');
ini_set('sendmail_from', $this->Sender);
}
@@ -1821,7 +1884,17 @@
if ($this->SingleTo && count($toArr) > 1) {
foreach ($toArr as $toAddr) {
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
- $this->doCallback($result, [$toAddr], $this->cc, $this->bcc, $this->Subject, $body, $this->From, []);
+ $addrinfo = static::parseAddresses($toAddr);
+ $this->doCallback(
+ $result,
+ [[$addrinfo['address'], $addrinfo['name']]],
+ $this->cc,
+ $this->bcc,
+ $this->Subject,
+ $body,
+ $this->From,
+ []
+ );
}
} else {
$result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
@@ -1899,7 +1972,7 @@
}
$callbacks = [];
- // Attempt to send to all recipients
+ //Attempt to send to all recipients
foreach ([$this->to, $this->cc, $this->bcc] as $togroup) {
foreach ($togroup as $to) {
if (!$this->smtp->recipient($to[0], $this->dsn)) {
@@ -1910,11 +1983,11 @@
$isSent = true;
}
- $callbacks[] = ['issent' => $isSent, 'to' => $to[0]];
+ $callbacks[] = ['issent' => $isSent, 'to' => $to[0], 'name' => $to[1]];
}
}
- // Only send the DATA command if we have viable recipients
+ //Only send the DATA command if we have viable recipients
if ((count($this->all_recipients) > count($bad_rcpt)) && !$this->smtp->data($header . $body)) {
throw new Exception($this->lang('data_not_accepted'), self::STOP_CRITICAL);
}
@@ -1931,7 +2004,7 @@
foreach ($callbacks as $cb) {
$this->doCallback(
$cb['issent'],
- [$cb['to']],
+ [[$cb['to'], $cb['name']]],
[],
[],
$this->Subject,
@@ -1976,7 +2049,7 @@
$options = $this->SMTPOptions;
}
- // Already connected?
+ //Already connected?
if ($this->smtp->connected()) {
return true;
}
@@ -1998,14 +2071,14 @@
)
) {
$this->edebug($this->lang('invalid_hostentry') . ' ' . trim($hostentry));
- // Not a valid host entry
+ //Not a valid host entry
continue;
}
- // $hostinfo[1]: optional ssl or tls prefix
- // $hostinfo[2]: the hostname
- // $hostinfo[3]: optional port number
- // The host string prefix can temporarily override the current setting for SMTPSecure
- // If it's not specified, the default value is used
+ //$hostinfo[1]: optional ssl or tls prefix
+ //$hostinfo[2]: the hostname
+ //$hostinfo[3]: optional port number
+ //The host string prefix can temporarily override the current setting for SMTPSecure
+ //If it's not specified, the default value is used
//Check the host name is a valid name or IP address before trying to use it
if (!static::isValidHost($hostinfo[2])) {
@@ -2017,11 +2090,11 @@
$tls = (static::ENCRYPTION_STARTTLS === $this->SMTPSecure);
if ('ssl' === $hostinfo[1] || ('' === $hostinfo[1] && static::ENCRYPTION_SMTPS === $this->SMTPSecure)) {
$prefix = 'ssl://';
- $tls = false; // Can't have SSL and TLS at the same time
+ $tls = false; //Can't have SSL and TLS at the same time
$secure = static::ENCRYPTION_SMTPS;
} elseif ('tls' === $hostinfo[1]) {
$tls = true;
- // tls doesn't use a prefix
+ //TLS doesn't use a prefix
$secure = static::ENCRYPTION_STARTTLS;
}
//Do we need the OpenSSL extension?
@@ -2051,10 +2124,10 @@
}
$this->smtp->hello($hello);
//Automatically enable TLS encryption if:
- // * it's not disabled
- // * we have openssl extension
- // * we are not already using SSL
- // * the server offers STARTTLS
+ //* it's not disabled
+ //* we have openssl extension
+ //* we are not already using SSL
+ //* the server offers STARTTLS
if ($this->SMTPAutoTLS && $sslext && 'ssl' !== $secure && $this->smtp->getServerExt('STARTTLS')) {
$tls = true;
}
@@ -2062,7 +2135,7 @@
if (!$this->smtp->startTLS()) {
throw new Exception($this->lang('connect_host'));
}
- // We must resend EHLO after TLS negotiation
+ //We must resend EHLO after TLS negotiation
$this->smtp->hello($hello);
}
if (
@@ -2080,14 +2153,14 @@
} catch (Exception $exc) {
$lastexception = $exc;
$this->edebug($exc->getMessage());
- // We must have connected, but then failed TLS or Auth, so close connection nicely
+ //We must have connected, but then failed TLS or Auth, so close connection nicely
$this->smtp->quit();
}
}
}
- // If we get here, all connection attempts have failed, so close connection hard
+ //If we get here, all connection attempts have failed, so close connection hard
$this->smtp->close();
- // As we've caught all exceptions, just report whatever the last one was
+ //As we've caught all exceptions, just report whatever the last one was
if ($this->exceptions && null !== $lastexception) {
throw $lastexception;
}
@@ -2112,13 +2185,14 @@
* The default language is English.
*
* @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
- * @param string $lang_path Path to the language file directory, with trailing separator (slash)
+ * @param string $lang_path Path to the language file directory, with trailing separator (slash).D
+ * Do not set this from user input!
*
* @return bool
*/
public function setLanguage($langcode = 'en', $lang_path = '')
{
- // Backwards compatibility for renamed language codes
+ //Backwards compatibility for renamed language codes
$renamed_langcodes = [
'br' => 'pt_br',
'cz' => 'cs',
@@ -2134,7 +2208,7 @@
$langcode = $renamed_langcodes[$langcode];
}
- // Define full set of translatable strings in English
+ //Define full set of translatable strings in English
$PHPMAILER_LANG = [
'authenticate' => 'SMTP Error: Could not authenticate.',
'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
@@ -2159,7 +2233,7 @@
'extension_missing' => 'Extension missing: ',
];
if (empty($lang_path)) {
- // Calculate an absolute path so it can work if CWD is not here
+ //Calculate an absolute path so it can work if CWD is not here
$lang_path = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR;
}
//Validate $langcode
@@ -2168,20 +2242,38 @@
}
$foundlang = true;
$lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
- // There is no English translation file
+ //There is no English translation file
if ('en' !== $langcode) {
- // Make sure language file path is readable
+ //Make sure language file path is readable
if (!static::fileIsAccessible($lang_file)) {
$foundlang = false;
} else {
- // Overwrite language-specific strings.
- // This way we'll never have missing translation keys.
- $foundlang = include $lang_file;
+ //$foundlang = include $lang_file;
+ $lines = file($lang_file);
+ foreach ($lines as $line) {
+ //Translation file lines look like this:
+ //$PHPMAILER_LANG['authenticate'] = 'SMTP-Fehler: Authentifizierung fehlgeschlagen.';
+ //These files are parsed as text and not PHP so as to avoid the possibility of code injection
+ //See https://blog.stevenlevithan.com/archives/match-quoted-string
+ $matches = [];
+ if (
+ preg_match(
+ '/^\$PHPMAILER_LANG\[\'([a-z\d_]+)\'\]\s*=\s*(["\'])(.+)*?\2;/',
+ $line,
+ $matches
+ ) &&
+ //Ignore unknown translation keys
+ array_key_exists($matches[1], $PHPMAILER_LANG)
+ ) {
+ //Overwrite language-specific strings so we'll never have missing translation keys.
+ $PHPMAILER_LANG[$matches[1]] = (string)$matches[3];
+ }
+ }
}
}
$this->language = $PHPMAILER_LANG;
- return (bool) $foundlang; // Returns false if language not found
+ return $foundlang; //Returns false if language not found
}
/**
@@ -2225,7 +2317,7 @@
*/
public function addrFormat($addr)
{
- if (empty($addr[1])) { // No name provided
+ if (empty($addr[1])) { //No name provided
return $this->secureHeader($addr[0]);
}
@@ -2252,8 +2344,8 @@
} else {
$soft_break = static::$LE;
}
- // If utf-8 encoding is used, we will need to make sure we don't
- // split multibyte characters when we wrap
+ //If utf-8 encoding is used, we will need to make sure we don't
+ //split multibyte characters when we wrap
$is_utf8 = static::CHARSET_UTF8 === strtolower($this->CharSet);
$lelen = strlen(static::$LE);
$crlflen = strlen(static::$LE);
@@ -2353,29 +2445,29 @@
$lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
$encodedCharPos = strpos($lastChunk, '=');
if (false !== $encodedCharPos) {
- // Found start of encoded character byte within $lookBack block.
- // Check the encoded byte value (the 2 chars after the '=')
+ //Found start of encoded character byte within $lookBack block.
+ //Check the encoded byte value (the 2 chars after the '=')
$hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
$dec = hexdec($hex);
if ($dec < 128) {
- // Single byte character.
- // If the encoded char was found at pos 0, it will fit
- // otherwise reduce maxLength to start of the encoded char
+ //Single byte character.
+ //If the encoded char was found at pos 0, it will fit
+ //otherwise reduce maxLength to start of the encoded char
if ($encodedCharPos > 0) {
$maxLength -= $lookBack - $encodedCharPos;
}
$foundSplitPos = true;
} elseif ($dec >= 192) {
- // First byte of a multi byte character
- // Reduce maxLength to split at start of character
+ //First byte of a multi byte character
+ //Reduce maxLength to split at start of character
$maxLength -= $lookBack - $encodedCharPos;
$foundSplitPos = true;
} elseif ($dec < 192) {
- // Middle byte of a multi byte character, look further back
+ //Middle byte of a multi byte character, look further back
$lookBack += 3;
}
} else {
- // No encoded character found
+ //No encoded character found
$foundSplitPos = true;
}
}
@@ -2419,7 +2511,7 @@
$result .= $this->headerLine('Date', '' === $this->MessageDate ? self::rfcDate() : $this->MessageDate);
- // The To header is created automatically by mail(), so needs to be omitted here
+ //The To header is created automatically by mail(), so needs to be omitted here
if ('mail' !== $this->Mailer) {
if ($this->SingleTo) {
foreach ($this->to as $toaddr) {
@@ -2433,12 +2525,12 @@
}
$result .= $this->addrAppend('From', [[trim($this->From), $this->FromName]]);
- // sendmail and mail() extract Cc from the header before sending
+ //sendmail and mail() extract Cc from the header before sending
if (count($this->cc) > 0) {
$result .= $this->addrAppend('Cc', $this->cc);
}
- // sendmail and mail() extract Bcc from the header before sending
+ //sendmail and mail() extract Bcc from the header before sending
if (
(
'sendmail' === $this->Mailer || 'qmail' === $this->Mailer || 'mail' === $this->Mailer
@@ -2452,13 +2544,13 @@
$result .= $this->addrAppend('Reply-To', $this->ReplyTo);
}
- // mail() sets the subject itself
+ //mail() sets the subject itself
if ('mail' !== $this->Mailer) {
$result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
}
- // Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4
- // https://tools.ietf.org/html/rfc5322#section-3.6.4
+ //Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4
+ //https://tools.ietf.org/html/rfc5322#section-3.6.4
if ('' !== $this->MessageID && preg_match('/^<.*@.*>$/', $this->MessageID)) {
$this->lastMessageID = $this->MessageID;
} else {
@@ -2484,7 +2576,7 @@
$result .= $this->headerLine('Disposition-Notification-To', '<' . $this->ConfirmReadingTo . '>');
}
- // Add custom headers
+ //Add custom headers
foreach ($this->CustomHeader as $header) {
$result .= $this->headerLine(
trim($header[0]),
@@ -2526,28 +2618,24 @@
$result .= $this->textLine(' boundary="' . $this->boundary[1] . '"');
break;
default:
- // Catches case 'plain': and case '':
+ //Catches case 'plain': and case '':
$result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet);
$ismultipart = false;
break;
}
- // RFC1341 part 5 says 7bit is assumed if not specified
+ //RFC1341 part 5 says 7bit is assumed if not specified
if (static::ENCODING_7BIT !== $this->Encoding) {
- // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
+ //RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
if ($ismultipart) {
if (static::ENCODING_8BIT === $this->Encoding) {
$result .= $this->headerLine('Content-Transfer-Encoding', static::ENCODING_8BIT);
}
- // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
+ //The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
} else {
$result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding);
}
}
- if ('mail' !== $this->Mailer) {
-// $result .= static::$LE;
- }
-
return $result;
}
@@ -2816,7 +2904,7 @@
$body .= $this->attachAll('attachment', $this->boundary[1]);
break;
default:
- // Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types
+ //Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types
//Reset the `Encoding` property in case we changed it for line length reasons
$this->Encoding = $bodyEncoding;
$body .= $this->encodeString($this->Body, $this->Encoding);
@@ -2907,7 +2995,7 @@
$result .= $this->textLine('--' . $boundary);
$result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
$result .= static::$LE;
- // RFC1341 part 5 says 7bit is assumed if not specified
+ //RFC1341 part 5 says 7bit is assumed if not specified
if (static::ENCODING_7BIT !== $encoding) {
$result .= $this->headerLine('Content-Transfer-Encoding', $encoding);
}
@@ -3005,7 +3093,7 @@
throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
}
- // If a MIME type is not specified, try to work it out from the file name
+ //If a MIME type is not specified, try to work it out from the file name
if ('' === $type) {
$type = static::filenameToType($path);
}
@@ -3024,7 +3112,7 @@
2 => $name,
3 => $encoding,
4 => $type,
- 5 => false, // isStringAttachment
+ 5 => false, //isStringAttachment
6 => $disposition,
7 => $name,
];
@@ -3064,16 +3152,16 @@
*/
protected function attachAll($disposition_type, $boundary)
{
- // Return text of body
+ //Return text of body
$mime = [];
$cidUniq = [];
$incl = [];
- // Add all attachments
+ //Add all attachments
foreach ($this->attachment as $attachment) {
- // Check if it is a valid disposition_filter
+ //Check if it is a valid disposition_filter
if ($attachment[6] === $disposition_type) {
- // Check for string attachment
+ //Check for string attachment
$string = '';
$path = '';
$bString = $attachment[5];
@@ -3114,7 +3202,7 @@
static::$LE
);
}
- // RFC1341 part 5 says 7bit is assumed if not specified
+ //RFC1341 part 5 says 7bit is assumed if not specified
if (static::ENCODING_7BIT !== $encoding) {
$mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, static::$LE);
}
@@ -3124,7 +3212,7 @@
$mime[] = 'Content-ID: <' . $this->encodeHeader($this->secureHeader($cid)) . '>' . static::$LE;
}
- // Allow for bypassing the Content-Disposition header
+ //Allow for bypassing the Content-Disposition header
if (!empty($disposition)) {
$encoded_name = $this->encodeHeader($this->secureHeader($name));
if (!empty($encoded_name)) {
@@ -3145,7 +3233,7 @@
$mime[] = static::$LE;
}
- // Encode as string attachment
+ //Encode as string attachment
if ($bString) {
$mime[] = $this->encodeString($string, $encoding);
} else {
@@ -3221,7 +3309,7 @@
case static::ENCODING_7BIT:
case static::ENCODING_8BIT:
$encoded = static::normalizeBreaks($str);
- // Make sure it ends with a line break
+ //Make sure it ends with a line break
if (substr($encoded, -(strlen(static::$LE))) !== static::$LE) {
$encoded .= static::$LE;
}
@@ -3259,7 +3347,7 @@
switch (strtolower($position)) {
case 'phrase':
if (!preg_match('/[\200-\377]/', $str)) {
- // Can't use addslashes as we don't know the value of magic_quotes_sybase
+ //Can't use addslashes as we don't know the value of magic_quotes_sybase
$encoded = addcslashes($str, "\0..\37\177\\\"");
if (($str === $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
return $encoded;
@@ -3285,7 +3373,7 @@
$charset = static::CHARSET_ASCII;
}
- // Q/B encoding adds 8 chars and the charset ("` =?<charset>?[QB]?<content>?=`").
+ //Q/B encoding adds 8 chars and the charset ("` =?<charset>?[QB]?<content>?=`").
$overhead = 8 + strlen($charset);
if ('mail' === $this->Mailer) {
@@ -3294,26 +3382,26 @@
$maxlen = static::MAX_LINE_LENGTH - $overhead;
}
- // Select the encoding that produces the shortest output and/or prevents corruption.
+ //Select the encoding that produces the shortest output and/or prevents corruption.
if ($matchcount > strlen($str) / 3) {
- // More than 1/3 of the content needs encoding, use B-encode.
+ //More than 1/3 of the content needs encoding, use B-encode.
$encoding = 'B';
} elseif ($matchcount > 0) {
- // Less than 1/3 of the content needs encoding, use Q-encode.
+ //Less than 1/3 of the content needs encoding, use Q-encode.
$encoding = 'Q';
} elseif (strlen($str) > $maxlen) {
- // No encoding needed, but value exceeds max line length, use Q-encode to prevent corruption.
+ //No encoding needed, but value exceeds max line length, use Q-encode to prevent corruption.
$encoding = 'Q';
} else {
- // No reformatting needed
+ //No reformatting needed
$encoding = false;
}
switch ($encoding) {
case 'B':
if ($this->hasMultiBytes($str)) {
- // Use a custom function which correctly encodes and wraps long
- // multibyte strings without breaking lines within a character
+ //Use a custom function which correctly encodes and wraps long
+ //multibyte strings without breaking lines within a character
$encoded = $this->base64EncodeWrapMB($str, "\n");
} else {
$encoded = base64_encode($str);
@@ -3348,7 +3436,7 @@
return strlen($str) > mb_strlen($str, $this->CharSet);
}
- // Assume no multibytes (we can't handle without mbstring functions anyway)
+ //Assume no multibytes (we can't handle without mbstring functions anyway)
return false;
}
@@ -3386,11 +3474,11 @@
}
$mb_length = mb_strlen($str, $this->CharSet);
- // Each line must have length <= 75, including $start and $end
+ //Each line must have length <= 75, including $start and $end
$length = 75 - strlen($start) - strlen($end);
- // Average multi-byte ratio
+ //Average multi-byte ratio
$ratio = $mb_length / strlen($str);
- // Base64 has a 4:3 ratio
+ //Base64 has a 4:3 ratio
$avgLength = floor($length * $ratio * .75);
$offset = 0;
@@ -3405,7 +3493,7 @@
$encoded .= $chunk . $linebreak;
}
- // Chomp the last linefeed
+ //Chomp the last linefeed
return substr($encoded, 0, -strlen($linebreak));
}
@@ -3434,12 +3522,12 @@
*/
public function encodeQ($str, $position = 'text')
{
- // There should not be any EOL in the string
+ //There should not be any EOL in the string
$pattern = '';
$encoded = str_replace(["\r", "\n"], '', $str);
switch (strtolower($position)) {
case 'phrase':
- // RFC 2047 section 5.3
+ //RFC 2047 section 5.3
$pattern = '^A-Za-z0-9!*+\/ -';
break;
/*
@@ -3452,15 +3540,15 @@
/* Intentional fall through */
case 'text':
default:
- // RFC 2047 section 5.1
- // Replace every high ascii, control, =, ? and _ characters
+ //RFC 2047 section 5.1
+ //Replace every high ascii, control, =, ? and _ characters
$pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
break;
}
$matches = [];
if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
- // If the string contains an '=', make sure it's the first thing we replace
- // so as to avoid double-encoding
+ //If the string contains an '=', make sure it's the first thing we replace
+ //so as to avoid double-encoding
$eqkey = array_search('=', $matches[0], true);
if (false !== $eqkey) {
unset($matches[0][$eqkey]);
@@ -3470,8 +3558,8 @@
$encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);
}
}
- // Replace spaces with _ (more readable than =20)
- // RFC 2047 section 4.2(2)
+ //Replace spaces with _ (more readable than =20)
+ //RFC 2047 section 4.2(2)
return str_replace(' ', '_', $encoded);
}
@@ -3498,7 +3586,7 @@
$disposition = 'attachment'
) {
try {
- // If a MIME type is not specified, try to work it out from the file name
+ //If a MIME type is not specified, try to work it out from the file name
if ('' === $type) {
$type = static::filenameToType($filename);
}
@@ -3507,14 +3595,14 @@
throw new Exception($this->lang('encoding') . $encoding);
}
- // Append to $attachment array
+ //Append to $attachment array
$this->attachment[] = [
0 => $string,
1 => $filename,
2 => static::mb_pathinfo($filename, PATHINFO_BASENAME),
3 => $encoding,
4 => $type,
- 5 => true, // isStringAttachment
+ 5 => true, //isStringAttachment
6 => $disposition,
7 => 0,
];
@@ -3565,7 +3653,7 @@
throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
}
- // If a MIME type is not specified, try to work it out from the file name
+ //If a MIME type is not specified, try to work it out from the file name
if ('' === $type) {
$type = static::filenameToType($path);
}
@@ -3579,14 +3667,14 @@
$name = $filename;
}
- // Append to $attachment array
+ //Append to $attachment array
$this->attachment[] = [
0 => $path,
1 => $filename,
2 => $name,
3 => $encoding,
4 => $type,
- 5 => false, // isStringAttachment
+ 5 => false, //isStringAttachment
6 => $disposition,
7 => $cid,
];
@@ -3631,7 +3719,7 @@
$disposition = 'inline'
) {
try {
- // If a MIME type is not specified, try to work it out from the name
+ //If a MIME type is not specified, try to work it out from the name
if ('' === $type && !empty($name)) {
$type = static::filenameToType($name);
}
@@ -3640,14 +3728,14 @@
throw new Exception($this->lang('encoding') . $encoding);
}
- // Append to $attachment array
+ //Append to $attachment array
$this->attachment[] = [
0 => $string,
1 => $name,
2 => $name,
3 => $encoding,
4 => $type,
- 5 => true, // isStringAttachment
+ 5 => true, //isStringAttachment
6 => $disposition,
7 => $cid,
];
@@ -3867,8 +3955,8 @@
*/
public static function rfcDate()
{
- // Set the time zone to whatever the default is to avoid 500 errors
- // Will default to UTC if it's not set properly in php.ini
+ //Set the time zone to whatever the default is to avoid 500 errors
+ //Will default to UTC if it's not set properly in php.ini
date_default_timezone_set(@date_default_timezone_get());
return date('D, j M Y H:i:s O');
@@ -3946,13 +4034,13 @@
protected function lang($key)
{
if (count($this->language) < 1) {
- $this->setLanguage(); // set the default language
+ $this->setLanguage(); //Set the default language
}
if (array_key_exists($key, $this->language)) {
if ('smtp_connect_failed' === $key) {
- //Include a link to troubleshooting docs on SMTP connection failure
- //this is by far the biggest cause of support questions
+ //Include a link to troubleshooting docs on SMTP connection failure.
+ //This is by far the biggest cause of support questions
//but it's usually not PHPMailer's fault.
return $this->language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting';
}
@@ -3987,7 +4075,7 @@
public function addCustomHeader($name, $value = null)
{
if (null === $value && strpos($name, ':') !== false) {
- // Value passed in as name:value
+ //Value passed in as name:value
list($name, $value) = explode(':', $name, 2);
}
$name = trim($name);
@@ -4041,11 +4129,11 @@
preg_match_all('/(?<!-)(src|background)=["\'](.*)["\']/Ui', $message, $images);
if (array_key_exists(2, $images)) {
if (strlen($basedir) > 1 && '/' !== substr($basedir, -1)) {
- // Ensure $basedir has a trailing /
+ //Ensure $basedir has a trailing /
$basedir .= '/';
}
foreach ($images[2] as $imgindex => $url) {
- // Convert data URIs into embedded images
+ //Convert data URIs into embedded images
//e.g. "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
$match = [];
if (preg_match('#^data:(image/(?:jpe?g|gif|png));?(base64)?,(.+)#', $url, $match)) {
@@ -4059,7 +4147,7 @@
}
//Hash the decoded data, not the URL, so that the same data-URI image used in multiple places
//will only be embedded once, even if it used a different encoding
- $cid = substr(hash('sha256', $data), 0, 32) . '@phpmailer.0'; // RFC2392 S 2
+ $cid = substr(hash('sha256', $data), 0, 32) . '@phpmailer.0'; //RFC2392 S 2
if (!$this->cidExists($cid)) {
$this->addStringEmbeddedImage(
@@ -4078,13 +4166,13 @@
continue;
}
if (
- // Only process relative URLs if a basedir is provided (i.e. no absolute local paths)
+ //Only process relative URLs if a basedir is provided (i.e. no absolute local paths)
!empty($basedir)
- // Ignore URLs containing parent dir traversal (..)
+ //Ignore URLs containing parent dir traversal (..)
&& (strpos($url, '..') === false)
- // Do not change urls that are already inline images
+ //Do not change urls that are already inline images
&& 0 !== strpos($url, 'cid:')
- // Do not change absolute URLs, including anonymous protocol
+ //Do not change absolute URLs, including anonymous protocol
&& !preg_match('#^[a-z][a-z0-9+.-]*:?//#i', $url)
) {
$filename = static::mb_pathinfo($url, PATHINFO_BASENAME);
@@ -4092,7 +4180,7 @@
if ('.' === $directory) {
$directory = '';
}
- // RFC2392 S 2
+ //RFC2392 S 2
$cid = substr(hash('sha256', $url), 0, 32) . '@phpmailer.0';
if (strlen($basedir) > 1 && '/' !== substr($basedir, -1)) {
$basedir .= '/';
@@ -4119,7 +4207,7 @@
}
}
$this->isHTML();
- // Convert all message body line breaks to LE, makes quoted-printable encoding work much better
+ //Convert all message body line breaks to LE, makes quoted-printable encoding work much better
$this->Body = static::normalizeBreaks($message);
$this->AltBody = static::normalizeBreaks($this->html2text($message, $advanced));
if (!$this->alternativeExists()) {
@@ -4138,9 +4226,9 @@
* Example usage:
*
* ```php
- * // Use default conversion
+ * //Use default conversion
* $plain = $mail->html2text($html);
- * // Use your own custom converter
+ * //Use your own custom converter
* $plain = $mail->html2text($html, function($html) {
* $converter = new MyHtml2text($html);
* return $converter->get_text();
@@ -4307,7 +4395,7 @@
*/
public static function filenameToType($filename)
{
- // In case the path is a URL, strip any query string before getting extension
+ //In case the path is a URL, strip any query string before getting extension
$qpos = strpos($filename, '?');
if (false !== $qpos) {
$filename = substr($filename, 0, $qpos);
@@ -4418,9 +4506,9 @@
if (null === $breaktype) {
$breaktype = static::$LE;
}
- // Normalise to \n
+ //Normalise to \n
$text = str_replace([self::CRLF, "\r"], "\n", $text);
- // Now convert LE as needed
+ //Now convert LE as needed
if ("\n" !== $breaktype) {
$text = str_replace("\n", $breaktype, $text);
}
@@ -4526,13 +4614,13 @@
$privKey = openssl_pkey_get_private($privKeyStr);
}
if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) {
- if (PHP_MAJOR_VERSION < 8) {
+ if (\PHP_MAJOR_VERSION < 8) {
openssl_pkey_free($privKey);
}
return base64_encode($signature);
}
- if (PHP_MAJOR_VERSION < 8) {
+ if (\PHP_MAJOR_VERSION < 8) {
openssl_pkey_free($privKey);
}
@@ -4599,7 +4687,7 @@
if (empty($body)) {
return self::CRLF;
}
- // Normalize line endings to CRLF
+ //Normalize line endings to CRLF
$body = static::normalizeBreaks($body, self::CRLF);
//Reduce multiple trailing line breaks to a single one
@@ -4619,9 +4707,9 @@
*/
public function DKIM_Add($headers_line, $subject, $body)
{
- $DKIMsignatureType = 'rsa-sha256'; // Signature & hash algorithms
- $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization methods of header & body
- $DKIMquery = 'dns/txt'; // Query method
+ $DKIMsignatureType = 'rsa-sha256'; //Signature & hash algorithms
+ $DKIMcanonicalization = 'relaxed/simple'; //Canonicalization methods of header & body
+ $DKIMquery = 'dns/txt'; //Query method
$DKIMtime = time();
//Always sign these headers without being asked
//Recommended list from https://tools.ietf.org/html/rfc6376#section-5.4.1
@@ -4722,7 +4810,8 @@
$headerKeys = ' h=' . implode(':', $headersToSignKeys) . ';' . static::$LE;
$headerValues = implode(static::$LE, $headersToSign);
$body = $this->DKIM_BodyC($body);
- $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body
+ //Base64 of packed binary SHA-256 hash of body
+ $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body)));
$ident = '';
if ('' !== $this->DKIM_identity) {
$ident = ' i=' . $this->DKIM_identity . ';' . static::$LE;
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/POP3.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/POP3.php
index 235e637..b38964b 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/POP3.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/POP3.php
@@ -46,7 +46,7 @@
*
* @var string
*/
- const VERSION = '6.2.0';
+ const VERSION = '6.5.0';
/**
* Default POP3 port number.
@@ -199,13 +199,13 @@
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
{
$this->host = $host;
- // If no port value provided, use default
+ //If no port value provided, use default
if (false === $port) {
$this->port = static::DEFAULT_PORT;
} else {
$this->port = (int) $port;
}
- // If no timeout value provided, use default
+ //If no timeout value provided, use default
if (false === $timeout) {
$this->tval = static::DEFAULT_TIMEOUT;
} else {
@@ -214,9 +214,9 @@
$this->do_debug = $debug_level;
$this->username = $username;
$this->password = $password;
- // Reset the error log
+ //Reset the error log
$this->errors = [];
- // connect
+ //Connect
$result = $this->connect($this->host, $this->port, $this->tval);
if ($result) {
$login_result = $this->login($this->username, $this->password);
@@ -226,7 +226,7 @@
return true;
}
}
- // We need to disconnect regardless of whether the login succeeded
+ //We need to disconnect regardless of whether the login succeeded
$this->disconnect();
return false;
@@ -243,7 +243,7 @@
*/
public function connect($host, $port = false, $tval = 30)
{
- // Are we already connected?
+ //Are we already connected?
if ($this->connected) {
return true;
}
@@ -256,22 +256,22 @@
$port = static::DEFAULT_PORT;
}
- // connect to the POP3 server
+ //Connect to the POP3 server
$errno = 0;
$errstr = '';
$this->pop_conn = fsockopen(
- $host, // POP3 Host
- $port, // Port #
- $errno, // Error Number
- $errstr, // Error Message
+ $host, //POP3 Host
+ $port, //Port #
+ $errno, //Error Number
+ $errstr, //Error Message
$tval
- ); // Timeout (seconds)
- // Restore the error handler
+ ); //Timeout (seconds)
+ //Restore the error handler
restore_error_handler();
- // Did we connect?
+ //Did we connect?
if (false === $this->pop_conn) {
- // It would appear not...
+ //It would appear not...
$this->setError(
"Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr"
);
@@ -279,14 +279,14 @@
return false;
}
- // Increase the stream time-out
+ //Increase the stream time-out
stream_set_timeout($this->pop_conn, $tval, 0);
- // Get the POP3 server response
+ //Get the POP3 server response
$pop3_response = $this->getResponse();
- // Check for the +OK
+ //Check for the +OK
if ($this->checkResponse($pop3_response)) {
- // The connection is established and the POP3 server is talking
+ //The connection is established and the POP3 server is talking
$this->connected = true;
return true;
@@ -316,11 +316,11 @@
$password = $this->password;
}
- // Send the Username
+ //Send the Username
$this->sendString("USER $username" . static::LE);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
- // Send the Password
+ //Send the Password
$this->sendString("PASS $password" . static::LE);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/SMTP.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/SMTP.php
index ab7f46e..a4a91ed 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/SMTP.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/phpmailer/phpmailer/src/SMTP.php
@@ -35,7 +35,7 @@
*
* @var string
*/
- const VERSION = '6.2.0';
+ const VERSION = '6.5.0';
/**
* SMTP line break constant.
@@ -186,6 +186,7 @@
'Amazon_SES' => '/[\d]{3} Ok (.*)/',
'SendGrid' => '/[\d]{3} Ok: queued as (.*)/',
'CampaignMonitor' => '/[\d]{3} 2.0.0 OK:([a-zA-Z\d]{48})/',
+ 'Haraka' => '/[\d]{3} Message Queued \((.*)\)/',
];
/**
@@ -312,11 +313,11 @@
*/
public function connect($host, $port = null, $timeout = 30, $options = [])
{
- // Clear errors to avoid confusion
+ //Clear errors to avoid confusion
$this->setError('');
- // Make sure we are __not__ connected
+ //Make sure we are __not__ connected
if ($this->connected()) {
- // Already connected, generate error
+ //Already connected, generate error
$this->setError('Already connected to a server');
return false;
@@ -324,7 +325,7 @@
if (empty($port)) {
$port = self::DEFAULT_PORT;
}
- // Connect to the SMTP server
+ //Connect to the SMTP server
$this->edebug(
"Connection: opening to $host:$port, timeout=$timeout, options=" .
(count($options) > 0 ? var_export($options, true) : 'array()'),
@@ -340,11 +341,23 @@
$this->edebug('Connection: opened', self::DEBUG_CONNECTION);
- // Get any announcement
+ //Get any announcement
$this->last_reply = $this->get_lines();
$this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
-
- return true;
+ $responseCode = (int)substr($this->last_reply, 0, 3);
+ if ($responseCode === 220) {
+ return true;
+ }
+ //Anything other than a 220 response means something went wrong
+ //RFC 5321 says the server will wait for us to send a QUIT in response to a 554 error
+ //https://tools.ietf.org/html/rfc5321#section-3.1
+ if ($responseCode === 554) {
+ $this->quit();
+ }
+ //This will handle 421 responses which may not wait for a QUIT (e.g. if the server is being shut down)
+ $this->edebug('Connection: closing due to error', self::DEBUG_CONNECTION);
+ $this->close();
+ return false;
}
/**
@@ -397,7 +410,7 @@
restore_error_handler();
}
- // Verify we connected properly
+ //Verify we connected properly
if (!is_resource($connection)) {
$this->setError(
'Failed to connect to server',
@@ -414,11 +427,11 @@
return false;
}
- // SMTP server can take longer to respond, give longer timeout for first read
- // Windows does not have support for this timeout function
+ //SMTP server can take longer to respond, give longer timeout for first read
+ //Windows does not have support for this timeout function
if (strpos(PHP_OS, 'WIN') !== 0) {
$max = (int)ini_get('max_execution_time');
- // Don't bother if unlimited, or if set_time_limit is disabled
+ //Don't bother if unlimited, or if set_time_limit is disabled
if (0 !== $max && $timeout > $max && strpos(ini_get('disable_functions'), 'set_time_limit') === false) {
@set_time_limit($timeout);
}
@@ -449,7 +462,7 @@
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
}
- // Begin encrypted connection
+ //Begin encrypted connection
set_error_handler([$this, 'errorHandler']);
$crypto_ok = stream_socket_enable_crypto(
$this->smtp_conn,
@@ -487,11 +500,11 @@
}
if (array_key_exists('EHLO', $this->server_caps)) {
- // SMTP extensions are available; try to find a proper authentication method
+ //SMTP extensions are available; try to find a proper authentication method
if (!array_key_exists('AUTH', $this->server_caps)) {
$this->setError('Authentication is not allowed at this stage');
- // 'at this stage' means that auth may be allowed after the stage changes
- // e.g. after STARTTLS
+ //'at this stage' means that auth may be allowed after the stage changes
+ //e.g. after STARTTLS
return false;
}
@@ -535,12 +548,14 @@
}
switch ($authtype) {
case 'PLAIN':
- // Start authentication
+ //Start authentication
if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
return false;
}
- // Send encoded username and password
+ //Send encoded username and password
if (
+ //Format from https://tools.ietf.org/html/rfc4616#section-2
+ //We skip the first field (it's forgery), so the string starts with a null byte
!$this->sendCommand(
'User & Password',
base64_encode("\0" . $username . "\0" . $password),
@@ -551,7 +566,7 @@
}
break;
case 'LOGIN':
- // Start authentication
+ //Start authentication
if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
return false;
}
@@ -563,17 +578,17 @@
}
break;
case 'CRAM-MD5':
- // Start authentication
+ //Start authentication
if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
return false;
}
- // Get the challenge
+ //Get the challenge
$challenge = base64_decode(substr($this->last_reply, 4));
- // Build the response
+ //Build the response
$response = $username . ' ' . $this->hmac($challenge, $password);
- // send encoded credentials
+ //send encoded credentials
return $this->sendCommand('Username', base64_encode($response), 235);
case 'XOAUTH2':
//The OAuth instance must be set up prior to requesting auth.
@@ -582,7 +597,7 @@
}
$oauth = $OAuth->getOauth64();
- // Start authentication
+ //Start authentication
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
return false;
}
@@ -612,15 +627,15 @@
return hash_hmac('md5', $data, $key);
}
- // The following borrowed from
- // http://php.net/manual/en/function.mhash.php#27225
+ //The following borrowed from
+ //http://php.net/manual/en/function.mhash.php#27225
- // RFC 2104 HMAC implementation for php.
- // Creates an md5 HMAC.
- // Eliminates the need to install mhash to compute a HMAC
- // by Lance Rushing
+ //RFC 2104 HMAC implementation for php.
+ //Creates an md5 HMAC.
+ //Eliminates the need to install mhash to compute a HMAC
+ //by Lance Rushing
- $bytelen = 64; // byte length for md5
+ $bytelen = 64; //byte length for md5
if (strlen($key) > $bytelen) {
$key = pack('H*', md5($key));
}
@@ -643,7 +658,7 @@
if (is_resource($this->smtp_conn)) {
$sock_status = stream_get_meta_data($this->smtp_conn);
if ($sock_status['eof']) {
- // The socket is valid but we are not connected
+ //The socket is valid but we are not connected
$this->edebug(
'SMTP NOTICE: EOF caught while checking if connected',
self::DEBUG_CLIENT
@@ -653,7 +668,7 @@
return false;
}
- return true; // everything looks good
+ return true; //everything looks good
}
return false;
@@ -671,7 +686,7 @@
$this->server_caps = null;
$this->helo_rply = null;
if (is_resource($this->smtp_conn)) {
- // close the connection and cleanup
+ //Close the connection and cleanup
fclose($this->smtp_conn);
$this->smtp_conn = null; //Makes for cleaner serialization
$this->edebug('Connection: closed', self::DEBUG_CONNECTION);
@@ -706,7 +721,7 @@
* NOTE: this does not count towards line-length limit.
*/
- // Normalize line breaks before exploding
+ //Normalize line breaks before exploding
$lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data));
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
@@ -752,7 +767,8 @@
//Send the lines to the server
foreach ($lines_out as $line_out) {
- //RFC2821 section 4.5.2
+ //Dot-stuffing as per RFC5321 section 4.5.2
+ //https://tools.ietf.org/html/rfc5321#section-4.5.2
if (!empty($line_out) && $line_out[0] === '.') {
$line_out = '.' . $line_out;
}
@@ -786,7 +802,16 @@
public function hello($host = '')
{
//Try extended hello first (RFC 2821)
- return $this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host);
+ if ($this->sendHello('EHLO', $host)) {
+ return true;
+ }
+
+ //Some servers shut down the SMTP service here (RFC 5321)
+ if (substr($this->helo_rply, 0, 3) == '421') {
+ return false;
+ }
+
+ return $this->sendHello('HELO', $host);
}
/**
@@ -976,12 +1001,12 @@
$this->client_send($commandstring . static::LE, $command);
$this->last_reply = $this->get_lines();
- // Fetch SMTP code and possible error code explanation
+ //Fetch SMTP code and possible error code explanation
$matches = [];
if (preg_match('/^([\d]{3})[ -](?:([\d]\\.[\d]\\.[\d]{1,2}) )?/', $this->last_reply, $matches)) {
$code = (int) $matches[1];
$code_ex = (count($matches) > 2 ? $matches[2] : null);
- // Cut off error code from each response line
+ //Cut off error code from each response line
$detail = preg_replace(
"/{$code}[ -]" .
($code_ex ? str_replace('.', '\\.', $code_ex) . ' ' : '') . '/m',
@@ -989,7 +1014,7 @@
$this->last_reply
);
} else {
- // Fall back to simple parsing if regex fails
+ //Fall back to simple parsing if regex fails
$code = (int) substr($this->last_reply, 0, 3);
$code_ex = null;
$detail = substr($this->last_reply, 4);
@@ -1184,7 +1209,7 @@
*/
protected function get_lines()
{
- // If the connection is bad, give up straight away
+ //If the connection is bad, give up straight away
if (!is_resource($this->smtp_conn)) {
return '';
}
@@ -1237,13 +1262,13 @@
$str = @fgets($this->smtp_conn, self::MAX_REPLY_LENGTH);
$this->edebug('SMTP INBOUND: "' . trim($str) . '"', self::DEBUG_LOWLEVEL);
$data .= $str;
- // If response is only 3 chars (not valid, but RFC5321 S4.2 says it must be handled),
- // or 4th character is a space or a line break char, we are done reading, break the loop.
- // String array access is a significant micro-optimisation over strlen
+ //If response is only 3 chars (not valid, but RFC5321 S4.2 says it must be handled),
+ //or 4th character is a space or a line break char, we are done reading, break the loop.
+ //String array access is a significant micro-optimisation over strlen
if (!isset($str[3]) || $str[3] === ' ' || $str[3] === "\r" || $str[3] === "\n") {
break;
}
- // Timed-out? Log and break
+ //Timed-out? Log and break
$info = stream_get_meta_data($this->smtp_conn);
if ($info['timed_out']) {
$this->edebug(
@@ -1252,7 +1277,7 @@
);
break;
}
- // Now check if reads took too long
+ //Now check if reads took too long
if ($endtime && time() > $endtime) {
$this->edebug(
'SMTP -> get_lines(): timelimit reached (' .
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/.gitignore b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/.gitignore
new file mode 100644
index 0000000..b2395aa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/.gitignore
@@ -0,0 +1,3 @@
+composer.lock
+composer.phar
+/vendor/
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/LICENSE
new file mode 100644
index 0000000..2877a48
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2016 container-interop
+Copyright (c) 2016 PHP Framework Interoperability Group
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/README.md
new file mode 100644
index 0000000..1b9d9e5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/README.md
@@ -0,0 +1,13 @@
+Container interface
+==============
+
+This repository holds all interfaces related to [PSR-11 (Container Interface)][psr-url].
+
+Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container.
+
+The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.
+
+[psr-url]: https://www.php-fig.org/psr/psr-11/
+[package-url]: https://packagist.org/packages/psr/container
+[implementation-url]: https://packagist.org/providers/psr/container-implementation
+
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/composer.json
new file mode 100644
index 0000000..3797a25
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/composer.json
@@ -0,0 +1,22 @@
+{
+ "name": "psr/container",
+ "type": "library",
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"],
+ "homepage": "https://github.com/php-fig/container",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/src/ContainerExceptionInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/src/ContainerExceptionInterface.php
new file mode 100644
index 0000000..cf10b8b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/src/ContainerExceptionInterface.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Psr\Container;
+
+/**
+ * Base interface representing a generic exception in a container.
+ */
+interface ContainerExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/src/ContainerInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/src/ContainerInterface.php
new file mode 100644
index 0000000..cf8e7fd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/src/ContainerInterface.php
@@ -0,0 +1,36 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Psr\Container;
+
+/**
+ * Describes the interface of a container that exposes methods to read its entries.
+ */
+interface ContainerInterface
+{
+ /**
+ * Finds an entry of the container by its identifier and returns it.
+ *
+ * @param string $id Identifier of the entry to look for.
+ *
+ * @throws NotFoundExceptionInterface No entry was found for **this** identifier.
+ * @throws ContainerExceptionInterface Error while retrieving the entry.
+ *
+ * @return mixed Entry.
+ */
+ public function get(string $id);
+
+ /**
+ * Returns true if the container can return an entry for the given identifier.
+ * Returns false otherwise.
+ *
+ * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
+ * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
+ *
+ * @param string $id Identifier of the entry to look for.
+ *
+ * @return bool
+ */
+ public function has(string $id);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/src/NotFoundExceptionInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/src/NotFoundExceptionInterface.php
new file mode 100644
index 0000000..650bf46
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/container/src/NotFoundExceptionInterface.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Psr\Container;
+
+/**
+ * No entry was found in the container.
+ */
+interface NotFoundExceptionInterface extends ContainerExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/LICENSE
new file mode 100644
index 0000000..474c952
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012 PHP Framework Interoperability Group
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/AbstractLogger.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/AbstractLogger.php
new file mode 100644
index 0000000..e02f9da
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/AbstractLogger.php
@@ -0,0 +1,128 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * This is a simple Logger implementation that other Loggers can inherit from.
+ *
+ * It simply delegates all log-level-specific methods to the `log` method to
+ * reduce boilerplate code that a simple Logger that does the same thing with
+ * messages regardless of the error level has to implement.
+ */
+abstract class AbstractLogger implements LoggerInterface
+{
+ /**
+ * System is unusable.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function emergency($message, array $context = array())
+ {
+ $this->log(LogLevel::EMERGENCY, $message, $context);
+ }
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function alert($message, array $context = array())
+ {
+ $this->log(LogLevel::ALERT, $message, $context);
+ }
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function critical($message, array $context = array())
+ {
+ $this->log(LogLevel::CRITICAL, $message, $context);
+ }
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function error($message, array $context = array())
+ {
+ $this->log(LogLevel::ERROR, $message, $context);
+ }
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function warning($message, array $context = array())
+ {
+ $this->log(LogLevel::WARNING, $message, $context);
+ }
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function notice($message, array $context = array())
+ {
+ $this->log(LogLevel::NOTICE, $message, $context);
+ }
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function info($message, array $context = array())
+ {
+ $this->log(LogLevel::INFO, $message, $context);
+ }
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function debug($message, array $context = array())
+ {
+ $this->log(LogLevel::DEBUG, $message, $context);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/InvalidArgumentException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/InvalidArgumentException.php
new file mode 100644
index 0000000..67f852d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/InvalidArgumentException.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Psr\Log;
+
+class InvalidArgumentException extends \InvalidArgumentException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LogLevel.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LogLevel.php
new file mode 100644
index 0000000..9cebcac
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LogLevel.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * Describes log levels.
+ */
+class LogLevel
+{
+ const EMERGENCY = 'emergency';
+ const ALERT = 'alert';
+ const CRITICAL = 'critical';
+ const ERROR = 'error';
+ const WARNING = 'warning';
+ const NOTICE = 'notice';
+ const INFO = 'info';
+ const DEBUG = 'debug';
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerAwareInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerAwareInterface.php
new file mode 100644
index 0000000..4d64f47
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerAwareInterface.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * Describes a logger-aware instance.
+ */
+interface LoggerAwareInterface
+{
+ /**
+ * Sets a logger instance on the object.
+ *
+ * @param LoggerInterface $logger
+ *
+ * @return void
+ */
+ public function setLogger(LoggerInterface $logger);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerAwareTrait.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerAwareTrait.php
new file mode 100644
index 0000000..82bf45c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerAwareTrait.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * Basic Implementation of LoggerAwareInterface.
+ */
+trait LoggerAwareTrait
+{
+ /**
+ * The logger instance.
+ *
+ * @var LoggerInterface|null
+ */
+ protected $logger;
+
+ /**
+ * Sets a logger.
+ *
+ * @param LoggerInterface $logger
+ */
+ public function setLogger(LoggerInterface $logger)
+ {
+ $this->logger = $logger;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerInterface.php
new file mode 100644
index 0000000..2206cfd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerInterface.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * Describes a logger instance.
+ *
+ * The message MUST be a string or object implementing __toString().
+ *
+ * The message MAY contain placeholders in the form: {foo} where foo
+ * will be replaced by the context data in key "foo".
+ *
+ * The context array can contain arbitrary data. The only assumption that
+ * can be made by implementors is that if an Exception instance is given
+ * to produce a stack trace, it MUST be in a key named "exception".
+ *
+ * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
+ * for the full interface specification.
+ */
+interface LoggerInterface
+{
+ /**
+ * System is unusable.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function emergency($message, array $context = array());
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function alert($message, array $context = array());
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function critical($message, array $context = array());
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function error($message, array $context = array());
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function warning($message, array $context = array());
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function notice($message, array $context = array());
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function info($message, array $context = array());
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ */
+ public function debug($message, array $context = array());
+
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param mixed[] $context
+ *
+ * @return void
+ *
+ * @throws \Psr\Log\InvalidArgumentException
+ */
+ public function log($level, $message, array $context = array());
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerTrait.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerTrait.php
new file mode 100644
index 0000000..e392fef
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/LoggerTrait.php
@@ -0,0 +1,142 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * This is a simple Logger trait that classes unable to extend AbstractLogger
+ * (because they extend another class, etc) can include.
+ *
+ * It simply delegates all log-level-specific methods to the `log` method to
+ * reduce boilerplate code that a simple Logger that does the same thing with
+ * messages regardless of the error level has to implement.
+ */
+trait LoggerTrait
+{
+ /**
+ * System is unusable.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function emergency($message, array $context = array())
+ {
+ $this->log(LogLevel::EMERGENCY, $message, $context);
+ }
+
+ /**
+ * Action must be taken immediately.
+ *
+ * Example: Entire website down, database unavailable, etc. This should
+ * trigger the SMS alerts and wake you up.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function alert($message, array $context = array())
+ {
+ $this->log(LogLevel::ALERT, $message, $context);
+ }
+
+ /**
+ * Critical conditions.
+ *
+ * Example: Application component unavailable, unexpected exception.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function critical($message, array $context = array())
+ {
+ $this->log(LogLevel::CRITICAL, $message, $context);
+ }
+
+ /**
+ * Runtime errors that do not require immediate action but should typically
+ * be logged and monitored.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function error($message, array $context = array())
+ {
+ $this->log(LogLevel::ERROR, $message, $context);
+ }
+
+ /**
+ * Exceptional occurrences that are not errors.
+ *
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
+ * that are not necessarily wrong.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function warning($message, array $context = array())
+ {
+ $this->log(LogLevel::WARNING, $message, $context);
+ }
+
+ /**
+ * Normal but significant events.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function notice($message, array $context = array())
+ {
+ $this->log(LogLevel::NOTICE, $message, $context);
+ }
+
+ /**
+ * Interesting events.
+ *
+ * Example: User logs in, SQL logs.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function info($message, array $context = array())
+ {
+ $this->log(LogLevel::INFO, $message, $context);
+ }
+
+ /**
+ * Detailed debug information.
+ *
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ */
+ public function debug($message, array $context = array())
+ {
+ $this->log(LogLevel::DEBUG, $message, $context);
+ }
+
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ *
+ * @throws \Psr\Log\InvalidArgumentException
+ */
+ abstract public function log($level, $message, array $context = array());
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/NullLogger.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/NullLogger.php
new file mode 100644
index 0000000..c8f7293
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/NullLogger.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Psr\Log;
+
+/**
+ * This Logger can be used to avoid conditional log calls.
+ *
+ * Logging should always be optional, and if no logger is provided to your
+ * library creating a NullLogger instance to have something to throw logs at
+ * is a good way to avoid littering your code with `if ($this->logger) { }`
+ * blocks.
+ */
+class NullLogger extends AbstractLogger
+{
+ /**
+ * Logs with an arbitrary level.
+ *
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ *
+ * @return void
+ *
+ * @throws \Psr\Log\InvalidArgumentException
+ */
+ public function log($level, $message, array $context = array())
+ {
+ // noop
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/Test/DummyTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/Test/DummyTest.php
new file mode 100644
index 0000000..9638c11
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/Test/DummyTest.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Psr\Log\Test;
+
+/**
+ * This class is internal and does not follow the BC promise.
+ *
+ * Do NOT use this class in any way.
+ *
+ * @internal
+ */
+class DummyTest
+{
+ public function __toString()
+ {
+ return 'DummyTest';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
new file mode 100644
index 0000000..e1e5354
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace Psr\Log\Test;
+
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Provides a base test class for ensuring compliance with the LoggerInterface.
+ *
+ * Implementors can extend the class and implement abstract methods to run this
+ * as part of their test suite.
+ */
+abstract class LoggerInterfaceTest extends TestCase
+{
+ /**
+ * @return LoggerInterface
+ */
+ abstract public function getLogger();
+
+ /**
+ * This must return the log messages in order.
+ *
+ * The simple formatting of the messages is: "<LOG LEVEL> <MESSAGE>".
+ *
+ * Example ->error('Foo') would yield "error Foo".
+ *
+ * @return string[]
+ */
+ abstract public function getLogs();
+
+ public function testImplements()
+ {
+ $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
+ }
+
+ /**
+ * @dataProvider provideLevelsAndMessages
+ */
+ public function testLogsAtAllLevels($level, $message)
+ {
+ $logger = $this->getLogger();
+ $logger->{$level}($message, array('user' => 'Bob'));
+ $logger->log($level, $message, array('user' => 'Bob'));
+
+ $expected = array(
+ $level.' message of level '.$level.' with context: Bob',
+ $level.' message of level '.$level.' with context: Bob',
+ );
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function provideLevelsAndMessages()
+ {
+ return array(
+ LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
+ LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
+ LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
+ LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
+ LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
+ LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
+ LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
+ LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
+ );
+ }
+
+ /**
+ * @expectedException \Psr\Log\InvalidArgumentException
+ */
+ public function testThrowsOnInvalidLevel()
+ {
+ $logger = $this->getLogger();
+ $logger->log('invalid level', 'Foo');
+ }
+
+ public function testContextReplacement()
+ {
+ $logger = $this->getLogger();
+ $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
+
+ $expected = array('info {Message {nothing} Bob Bar a}');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testObjectCastToString()
+ {
+ if (method_exists($this, 'createPartialMock')) {
+ $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
+ } else {
+ $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
+ }
+ $dummy->expects($this->once())
+ ->method('__toString')
+ ->will($this->returnValue('DUMMY'));
+
+ $this->getLogger()->warning($dummy);
+
+ $expected = array('warning DUMMY');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testContextCanContainAnything()
+ {
+ $closed = fopen('php://memory', 'r');
+ fclose($closed);
+
+ $context = array(
+ 'bool' => true,
+ 'null' => null,
+ 'string' => 'Foo',
+ 'int' => 0,
+ 'float' => 0.5,
+ 'nested' => array('with object' => new DummyTest),
+ 'object' => new \DateTime,
+ 'resource' => fopen('php://memory', 'r'),
+ 'closed' => $closed,
+ );
+
+ $this->getLogger()->warning('Crazy context data', $context);
+
+ $expected = array('warning Crazy context data');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testContextExceptionKeyCanBeExceptionOrOtherValues()
+ {
+ $logger = $this->getLogger();
+ $logger->warning('Random message', array('exception' => 'oops'));
+ $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
+
+ $expected = array(
+ 'warning Random message',
+ 'critical Uncaught Exception!'
+ );
+ $this->assertEquals($expected, $this->getLogs());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/Test/TestLogger.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/Test/TestLogger.php
new file mode 100644
index 0000000..1be3230
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/Psr/Log/Test/TestLogger.php
@@ -0,0 +1,147 @@
+<?php
+
+namespace Psr\Log\Test;
+
+use Psr\Log\AbstractLogger;
+
+/**
+ * Used for testing purposes.
+ *
+ * It records all records and gives you access to them for verification.
+ *
+ * @method bool hasEmergency($record)
+ * @method bool hasAlert($record)
+ * @method bool hasCritical($record)
+ * @method bool hasError($record)
+ * @method bool hasWarning($record)
+ * @method bool hasNotice($record)
+ * @method bool hasInfo($record)
+ * @method bool hasDebug($record)
+ *
+ * @method bool hasEmergencyRecords()
+ * @method bool hasAlertRecords()
+ * @method bool hasCriticalRecords()
+ * @method bool hasErrorRecords()
+ * @method bool hasWarningRecords()
+ * @method bool hasNoticeRecords()
+ * @method bool hasInfoRecords()
+ * @method bool hasDebugRecords()
+ *
+ * @method bool hasEmergencyThatContains($message)
+ * @method bool hasAlertThatContains($message)
+ * @method bool hasCriticalThatContains($message)
+ * @method bool hasErrorThatContains($message)
+ * @method bool hasWarningThatContains($message)
+ * @method bool hasNoticeThatContains($message)
+ * @method bool hasInfoThatContains($message)
+ * @method bool hasDebugThatContains($message)
+ *
+ * @method bool hasEmergencyThatMatches($message)
+ * @method bool hasAlertThatMatches($message)
+ * @method bool hasCriticalThatMatches($message)
+ * @method bool hasErrorThatMatches($message)
+ * @method bool hasWarningThatMatches($message)
+ * @method bool hasNoticeThatMatches($message)
+ * @method bool hasInfoThatMatches($message)
+ * @method bool hasDebugThatMatches($message)
+ *
+ * @method bool hasEmergencyThatPasses($message)
+ * @method bool hasAlertThatPasses($message)
+ * @method bool hasCriticalThatPasses($message)
+ * @method bool hasErrorThatPasses($message)
+ * @method bool hasWarningThatPasses($message)
+ * @method bool hasNoticeThatPasses($message)
+ * @method bool hasInfoThatPasses($message)
+ * @method bool hasDebugThatPasses($message)
+ */
+class TestLogger extends AbstractLogger
+{
+ /**
+ * @var array
+ */
+ public $records = [];
+
+ public $recordsByLevel = [];
+
+ /**
+ * @inheritdoc
+ */
+ public function log($level, $message, array $context = [])
+ {
+ $record = [
+ 'level' => $level,
+ 'message' => $message,
+ 'context' => $context,
+ ];
+
+ $this->recordsByLevel[$record['level']][] = $record;
+ $this->records[] = $record;
+ }
+
+ public function hasRecords($level)
+ {
+ return isset($this->recordsByLevel[$level]);
+ }
+
+ public function hasRecord($record, $level)
+ {
+ if (is_string($record)) {
+ $record = ['message' => $record];
+ }
+ return $this->hasRecordThatPasses(function ($rec) use ($record) {
+ if ($rec['message'] !== $record['message']) {
+ return false;
+ }
+ if (isset($record['context']) && $rec['context'] !== $record['context']) {
+ return false;
+ }
+ return true;
+ }, $level);
+ }
+
+ public function hasRecordThatContains($message, $level)
+ {
+ return $this->hasRecordThatPasses(function ($rec) use ($message) {
+ return strpos($rec['message'], $message) !== false;
+ }, $level);
+ }
+
+ public function hasRecordThatMatches($regex, $level)
+ {
+ return $this->hasRecordThatPasses(function ($rec) use ($regex) {
+ return preg_match($regex, $rec['message']) > 0;
+ }, $level);
+ }
+
+ public function hasRecordThatPasses(callable $predicate, $level)
+ {
+ if (!isset($this->recordsByLevel[$level])) {
+ return false;
+ }
+ foreach ($this->recordsByLevel[$level] as $i => $rec) {
+ if (call_user_func($predicate, $rec, $i)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public function __call($method, $args)
+ {
+ if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
+ $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
+ $level = strtolower($matches[2]);
+ if (method_exists($this, $genericMethod)) {
+ $args[] = $level;
+ return call_user_func_array([$this, $genericMethod], $args);
+ }
+ }
+ throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
+ }
+
+ public function reset()
+ {
+ $this->records = [];
+ $this->recordsByLevel = [];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/README.md
new file mode 100644
index 0000000..a9f20c4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/README.md
@@ -0,0 +1,58 @@
+PSR Log
+=======
+
+This repository holds all interfaces/classes/traits related to
+[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md).
+
+Note that this is not a logger of its own. It is merely an interface that
+describes a logger. See the specification for more details.
+
+Installation
+------------
+
+```bash
+composer require psr/log
+```
+
+Usage
+-----
+
+If you need a logger, you can use the interface like this:
+
+```php
+<?php
+
+use Psr\Log\LoggerInterface;
+
+class Foo
+{
+ private $logger;
+
+ public function __construct(LoggerInterface $logger = null)
+ {
+ $this->logger = $logger;
+ }
+
+ public function doSomething()
+ {
+ if ($this->logger) {
+ $this->logger->info('Doing work');
+ }
+
+ try {
+ $this->doSomethingElse();
+ } catch (Exception $exception) {
+ $this->logger->error('Oh no!', array('exception' => $exception));
+ }
+
+ // do something useful
+ }
+}
+```
+
+You can then pick one of the implementations of the interface to get a logger.
+
+If you want to implement the interface, you can require this package and
+implement `Psr\Log\LoggerInterface` in your code. Please read the
+[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
+for details.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/composer.json
new file mode 100644
index 0000000..ca05695
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/log/composer.json
@@ -0,0 +1,26 @@
+{
+ "name": "psr/log",
+ "description": "Common interface for logging libraries",
+ "keywords": ["psr", "psr-3", "log"],
+ "homepage": "https://github.com/php-fig/log",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/.editorconfig b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/.editorconfig
new file mode 100644
index 0000000..48542cb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/.editorconfig
@@ -0,0 +1,12 @@
+; This file is for unifying the coding style for different editors and IDEs.
+; More information at http://editorconfig.org
+
+root = true
+
+[*]
+charset = utf-8
+indent_size = 4
+indent_style = space
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/LICENSE.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/LICENSE.md
new file mode 100644
index 0000000..e49a7c8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/LICENSE.md
@@ -0,0 +1,21 @@
+# The MIT License (MIT)
+
+Copyright (c) 2016 PHP Framework Interoperability Group
+
+> Permission is hereby granted, free of charge, to any person obtaining a copy
+> of this software and associated documentation files (the "Software"), to deal
+> in the Software without restriction, including without limitation the rights
+> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+> copies of the Software, and to permit persons to whom the Software is
+> furnished to do so, subject to the following conditions:
+>
+> The above copyright notice and this permission notice shall be included in
+> all copies or substantial portions of the Software.
+>
+> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+> THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/README.md
new file mode 100644
index 0000000..43641d1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/README.md
@@ -0,0 +1,8 @@
+PHP FIG Simple Cache PSR
+========================
+
+This repository holds all interfaces related to PSR-16.
+
+Note that this is not a cache implementation of its own. It is merely an interface that describes a cache implementation. See [the specification](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-16-simple-cache.md) for more details.
+
+You can find implementations of the specification by looking for packages providing the [psr/simple-cache-implementation](https://packagist.org/providers/psr/simple-cache-implementation) virtual package.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/composer.json
new file mode 100644
index 0000000..2978fa5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/composer.json
@@ -0,0 +1,25 @@
+{
+ "name": "psr/simple-cache",
+ "description": "Common interfaces for simple caching",
+ "keywords": ["psr", "psr-16", "cache", "simple-cache", "caching"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/src/CacheException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/src/CacheException.php
new file mode 100644
index 0000000..eba5381
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/src/CacheException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Psr\SimpleCache;
+
+/**
+ * Interface used for all types of exceptions thrown by the implementing library.
+ */
+interface CacheException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/src/CacheInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/src/CacheInterface.php
new file mode 100644
index 0000000..99e8d95
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/src/CacheInterface.php
@@ -0,0 +1,114 @@
+<?php
+
+namespace Psr\SimpleCache;
+
+interface CacheInterface
+{
+ /**
+ * Fetches a value from the cache.
+ *
+ * @param string $key The unique key of this item in the cache.
+ * @param mixed $default Default value to return if the key does not exist.
+ *
+ * @return mixed The value of the item from the cache, or $default in case of cache miss.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if the $key string is not a legal value.
+ */
+ public function get($key, $default = null);
+
+ /**
+ * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time.
+ *
+ * @param string $key The key of the item to store.
+ * @param mixed $value The value of the item to store, must be serializable.
+ * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and
+ * the driver supports TTL then the library may set a default value
+ * for it or let the driver take care of that.
+ *
+ * @return bool True on success and false on failure.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if the $key string is not a legal value.
+ */
+ public function set($key, $value, $ttl = null);
+
+ /**
+ * Delete an item from the cache by its unique key.
+ *
+ * @param string $key The unique cache key of the item to delete.
+ *
+ * @return bool True if the item was successfully removed. False if there was an error.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if the $key string is not a legal value.
+ */
+ public function delete($key);
+
+ /**
+ * Wipes clean the entire cache's keys.
+ *
+ * @return bool True on success and false on failure.
+ */
+ public function clear();
+
+ /**
+ * Obtains multiple cache items by their unique keys.
+ *
+ * @param iterable $keys A list of keys that can obtained in a single operation.
+ * @param mixed $default Default value to return for keys that do not exist.
+ *
+ * @return iterable A list of key => value pairs. Cache keys that do not exist or are stale will have $default as value.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if $keys is neither an array nor a Traversable,
+ * or if any of the $keys are not a legal value.
+ */
+ public function getMultiple($keys, $default = null);
+
+ /**
+ * Persists a set of key => value pairs in the cache, with an optional TTL.
+ *
+ * @param iterable $values A list of key => value pairs for a multiple-set operation.
+ * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and
+ * the driver supports TTL then the library may set a default value
+ * for it or let the driver take care of that.
+ *
+ * @return bool True on success and false on failure.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if $values is neither an array nor a Traversable,
+ * or if any of the $values are not a legal value.
+ */
+ public function setMultiple($values, $ttl = null);
+
+ /**
+ * Deletes multiple cache items in a single operation.
+ *
+ * @param iterable $keys A list of string-based keys to be deleted.
+ *
+ * @return bool True if the items were successfully removed. False if there was an error.
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if $keys is neither an array nor a Traversable,
+ * or if any of the $keys are not a legal value.
+ */
+ public function deleteMultiple($keys);
+
+ /**
+ * Determines whether an item is present in the cache.
+ *
+ * NOTE: It is recommended that has() is only to be used for cache warming type purposes
+ * and not to be used within your live applications operations for get/set, as this method
+ * is subject to a race condition where your has() will return true and immediately after,
+ * another script can remove it making the state of your app out of date.
+ *
+ * @param string $key The cache item key.
+ *
+ * @return bool
+ *
+ * @throws \Psr\SimpleCache\InvalidArgumentException
+ * MUST be thrown if the $key string is not a legal value.
+ */
+ public function has($key);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/src/InvalidArgumentException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/src/InvalidArgumentException.php
new file mode 100644
index 0000000..6a9524a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/psr/simple-cache/src/InvalidArgumentException.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Psr\SimpleCache;
+
+/**
+ * Exception interface for invalid cache arguments.
+ *
+ * When an invalid argument is passed it must throw an exception which implements
+ * this interface
+ */
+interface InvalidArgumentException extends CacheException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.github/FUNDING.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.github/FUNDING.yml
new file mode 100644
index 0000000..b2d7224
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.github/FUNDING.yml
@@ -0,0 +1,4 @@
+# These are supported funding model platforms
+
+github: [RobThree]
+custom: ["https://paypal.me/robiii"]
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.github/workflows/test.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.github/workflows/test.yml
new file mode 100644
index 0000000..8b31e23
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.github/workflows/test.yml
@@ -0,0 +1,27 @@
+name: Test
+
+on:
+ push:
+ pull_request:
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-version }}
+ tools: composer
+ coverage: xdebug
+
+ - uses: ramsey/composer-install@v1
+
+ - run: composer lint
+ - run: composer test
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.gitignore b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.gitignore
index 8a25841..5c1c961 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.gitignore
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.gitignore
@@ -125,7 +125,7 @@
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
-# TODO: Comment the next line if you want to checkin your web deploy settings
+# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
@@ -184,6 +184,9 @@
# Composer
/vendor
+composer.lock
# .vs
-.vs/
\ No newline at end of file
+.vs/
+
+.phpunit.result.cache
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.travis.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.travis.yml
deleted file mode 100644
index fdc6ff5..0000000
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/.travis.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-language: php
-
-php:
- - 5.6
- - 7.0
- - 7.1
- - 7.2
- - 7.3
- - 7.4
-
-before_script:
- - composer install
-
-script:
- - vendor/bin/phpunit --coverage-text tests
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/README.md
index 3574ae9..b8fcc75 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/README.md
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/README.md
@@ -1,6 +1,6 @@
# ![Logo](https://raw.githubusercontent.com/RobThree/TwoFactorAuth/master/logo.png) PHP library for Two Factor Authentication
-[![Build status](https://img.shields.io/travis/RobThree/TwoFactorAuth.svg?style=flat-square)](https://travis-ci.org/RobThree/TwoFactorAuth/) [![Latest Stable Version](https://img.shields.io/packagist/v/robthree/twofactorauth.svg?style=flat-square)](https://packagist.org/packages/robthree/twofactorauth) [![License](https://img.shields.io/packagist/l/robthree/twofactorauth.svg?style=flat-square)](LICENSE) [![Downloads](https://img.shields.io/packagist/dt/robthree/twofactorauth.svg?style=flat-square)](https://packagist.org/packages/robthree/twofactorauth) [![Code Climate](https://img.shields.io/codeclimate/github/RobThree/TwoFactorAuth.svg?style=flat-square)](https://codeclimate.com/github/RobThree/TwoFactorAuth) [![PayPal donate button](http://img.shields.io/badge/paypal-donate-orange.svg?style=flat-square)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6MB5M2SQLP636 "Keep me off the streets")
+[![Build status](https://img.shields.io/github/workflow/status/RobThree/TwoFactorAuth/Test/master?style=flat-square)](https://github.com/RobThree/TwoFactorAuth/actions?query=branch%3Amaster) [![Latest Stable Version](https://img.shields.io/packagist/v/robthree/twofactorauth.svg?style=flat-square)](https://packagist.org/packages/robthree/twofactorauth) [![License](https://img.shields.io/packagist/l/robthree/twofactorauth.svg?style=flat-square)](LICENSE) [![Downloads](https://img.shields.io/packagist/dt/robthree/twofactorauth.svg?style=flat-square)](https://packagist.org/packages/robthree/twofactorauth) [![Code Climate](https://img.shields.io/codeclimate/github/RobThree/TwoFactorAuth.svg?style=flat-square)](https://codeclimate.com/github/RobThree/TwoFactorAuth) [![PayPal donate button](http://img.shields.io/badge/paypal-donate-orange.svg?style=flat-square)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6MB5M2SQLP636 "Keep me off the streets")
PHP library for [two-factor (or multi-factor) authentication](http://en.wikipedia.org/wiki/Multi-factor_authentication) using [TOTP](http://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm) and [QR-codes](http://en.wikipedia.org/wiki/QR_code). Inspired by, based on but most importantly an *improvement* on '[PHPGangsta/GoogleAuthenticator](https://github.com/PHPGangsta/GoogleAuthenticator)'. There's a [.Net implementation](https://github.com/RobThree/TwoFactorAuth.Net) of this library as well.
@@ -10,10 +10,15 @@
## Requirements
-* Tested on PHP 5.6 up to 7.4
-* [cURL](http://php.net/manual/en/book.curl.php) when using the provided `ImageChartsQRCodeProvider` (default), `QRServerProvider` or `QRicketProvider` but you can also provide your own QR-code provider.
+* Tested on PHP 5.6 up to 8.0
+* [cURL](http://php.net/manual/en/book.curl.php) when using the provided `QRServerProvider` (default), `ImageChartsQRCodeProvider` or `QRicketProvider` but you can also provide your own QR-code provider.
* [random_bytes()](http://php.net/manual/en/function.random-bytes.php), [MCrypt](http://php.net/manual/en/book.mcrypt.php), [OpenSSL](http://php.net/manual/en/book.openssl.php) or [Hash](http://php.net/manual/en/book.hash.php) depending on which built-in RNG you use (TwoFactorAuth will try to 'autodetect' and use the best available); however: feel free to provide your own (CS)RNG.
+Optionally, you may need:
+
+* [endroid/qr-code](https://github.com/endroid/qr-code) if using `EndroidQrCodeProvider` or `EndroidQrCodeWithLogoProvider`.
+* [bacon/bacon-qr-code](https://github.com/Bacon/BaconQrCode) if using `BaconQrCodeProvider`.
+
## Installation
Run the following command:
@@ -35,17 +40,17 @@
The TwoFactorAuth class constructor accepts 7 arguments (all optional):
-Argument | Default value | Use
+Argument | Default value | Use
------------------|---------------|--------------------------------------------------
`$issuer` | `null` | Will be displayed in the app as issuer name
`$digits` | `6` | The number of digits the resulting codes will be
`$period` | `30` | The number of seconds a code will be valid
-`$algorithm` | `sha1` | The algorithm used
+`$algorithm` | `sha1` | The algorithm used (one of `sha1`, `sha256`, `sha512`, `md5`)
`$qrcodeprovider` | `null` | QR-code provider (more on this later)
`$rngprovider` | `null` | Random Number Generator provider (more on this later)
`$timeprovider` | `null` | Time provider (more on this later)
-These arguments are all '`write once`'; the class will, for it's lifetime, use these values when generating / calculating codes. The number of digits, the period and algorithm are all set to values Google's Authticator app uses (and supports). You may specify `8` digits, a period of `45` seconds and the `sha256` algorithm but the authenticator app (be it Google's implementation, Authy or any other app) may or may not support these values. Your mileage may vary; keep it on the safe side if you don't control which app your audience uses.
+These arguments are all '`write once`'; the class will, for it's lifetime, use these values when generating / calculating codes. The number of digits, the period and algorithm are all set to values Google's Authenticator app uses (and supports). You may specify `8` digits, a period of `45` seconds and the `sha256` algorithm but the authenticator app (be it Google's implementation, Authy or any other app) may or may not support these values. Your mileage may vary; keep it on the safe side if you don't control which app your audience uses.
### Step 1: Set up secret shared key
@@ -64,9 +69,12 @@
Another, more user-friendly, way to get the shared secret into the app is to generate a [QR-code](http://en.wikipedia.org/wiki/QR_code) which can be scanned by the app. To generate these QR codes you can use any one of the built-in `QRProvider` classes:
-1. `ImageChartsQRCodeProvider` (default)
-2. `QRServerProvider`
+1. `QRServerProvider` (default)
+2. `ImageChartsQRCodeProvider`
3. `QRicketProvider`
+4. `EndroidQrCodeProvider` (requires `endroid/qr-code` to be installed)
+5. `EndroidQrCodeWithLogoProvider` (same, but supporting embedded images)
+6. `BaconQrCodeProvider` (requires `bacon/bacon-qr-code` to be installed)
...or implement your own provider. To implement your own provider all you need to do is implement the `IQRCodeProvider` interface. You can use the built-in providers mentioned before to serve as an example or read the next chapter in this file. The built-in classes all use a 3rd (e.g. external) party (Image-charts, QRServer and QRicket) for the hard work of generating QR-codes (note: each of these services might at some point not be available or impose limitations to the number of codes generated per day, hour etc.). You could, however, easily use a project like [PHP QR Code](http://phpqrcode.sourceforge.net/) (or one of the [many others](https://packagist.org/search/?q=qr)) to generate your QR-codes without depending on external sources. Later on we'll [demonstrate](#qr-code-providers) how to do this.
@@ -89,7 +97,9 @@
$result = $tfa->verifyCode($_SESSION['secret'], $_POST['verification']);
````
-`verifyCode()` will return either `true` (the code was valid) or `false` (the code was invalid; no points for you!). You may need to store `$secret` in a `$_SESSION` or other persistent storage between requests. The `verifyCode()` accepts, aside from `$secret` and `$code`, three more arguments. The first being `$discrepancy`. Since TOTP codes are based on time("slices") it is very important that the server (but also client) have a correct date/time. But because the two *may* differ a bit we usually allow a certain amount of leeway. Because generated codes are valid for a specific period (remember the `$period` argument in the `TwoFactorAuth`'s constructor?) we usually check the period directly before and the period directly after the current time when validating codes. So when the current time is `14:34:21`, which results in a 'current timeslice' of `14:34:00` to `14:34:30` we also calculate/verify the codes for `14:33:30` to `14:34:00` and for `14:34:30` to `14:35:00`. This gives us a 'window' of `14:33:30` to `14:35:00`. The `$discrepancy` argument specifies how many periods (or: timeslices) we check in either direction of the current time. The default `$discrepancy` of `1` results in (max.) 3 period checks: -1, current and +1 period. A `$discrepancy` of `4` would result in a larger window (or: bigger time difference between client and server) of -4, -3, -2, -1, current, +1, +2, +3 and +4 periods.
+If you do extra validations with your `$_POST` values, just make sure the code is still submitted as string - even if that's a numeric code, casting it to integer is unreliable. Also, you may need to store `$secret` in a `$_SESSION` or other persistent storage between requests. `verifyCode()` will return either `true` (the code was valid) or `false` (the code was invalid; no points for you!).
+
+ The `verifyCode()` accepts, aside from `$secret` and `$code`, three more arguments, with the first being `$discrepancy`. Since TOTP codes are based on time("slices") it is very important that the server (but also client) have a correct date/time. But because the two *may* differ a bit we usually allow a certain amount of leeway. Because generated codes are valid for a specific period (remember the `$period` argument in the `TwoFactorAuth`'s constructor?) we usually check the period directly before and the period directly after the current time when validating codes. So when the current time is `14:34:21`, which results in a 'current timeslice' of `14:34:00` to `14:34:30` we also calculate/verify the codes for `14:33:30` to `14:34:00` and for `14:34:30` to `14:35:00`. This gives us a 'window' of `14:33:30` to `14:35:00`. The `$discrepancy` argument specifies how many periods (or: timeslices) we check in either direction of the current time. The default `$discrepancy` of `1` results in (max.) 3 period checks: -1, current and +1 period. A `$discrepancy` of `4` would result in a larger window (or: bigger time difference between client and server) of -4, -3, -2, -1, current, +1, +2, +3 and +4 periods.
The second, `$time`, allows you to check a code for a specific point in time. This argument has no real practical use but can be handy for unittesting etc. The default value, `null`, means: use the current time.
@@ -105,10 +115,10 @@
````php
public function __construct(
- $issuer = null,
+ $issuer = null,
$digits = 6,
- $period = 30,
- $algorithm = 'sha1',
+ $period = 30,
+ $algorithm = 'sha1',
RobThree\Auth\Providers\Qr\IQRCodeProvider $qrcodeprovider = null,
RobThree\Auth\Providers\Rng\IRNGProvider $rngprovider = null
);
@@ -119,9 +129,9 @@
### QR-code providers
-As mentioned before, this library comes with three 'built-in' QR-code providers. This chapter will touch the subject a bit but most of it should be self-explanatory. The `TwoFactorAuth`-class accepts a `$qrcodeprovider` argument which lets you specify a built-in or custom QR-code provider. All three built-in providers do a simple HTTP request to retrieve an image using cURL and implement the [`IQRCodeProvider`](lib/Providers/Qr/IQRCodeProvider.php) interface which is all you need to implement to write your own QR-code provider.
+As mentioned before, this library comes with five 'built-in' QR-code providers. This chapter will touch the subject a bit but most of it should be self-explanatory. The `TwoFactorAuth`-class accepts a `$qrcodeprovider` argument which lets you specify a built-in or custom QR-code provider. All five built-in providers do a simple HTTP request to retrieve an image using cURL and implement the [`IQRCodeProvider`](lib/Providers/Qr/IQRCodeProvider.php) interface which is all you need to implement to write your own QR-code provider.
-The default provider is the [`ImageChartsQRCodeProvider`](lib/Providers/Qr/ImageChartsQRCodeProvider.php) which uses the [image-charts.com replacement for Google Image Charts](https://image-charts.com) to render QR-codes. Then we have the [`QRServerProvider`](lib/Providers/Qr/QRServerProvider.php) which uses the [goqr.me API](http://goqr.me/api/doc/create-qr-code/) and finally we have the [`QRicketProvider`](lib/Providers/Qr/QRicketProvider.php) which uses the [QRickit API](http://qrickit.com/qrickit_apps/qrickit_api.php). All three inherit from a common (abstract) baseclass named [`BaseHTTPQRCodeProvider`](lib/Providers/Qr/BaseHTTPQRCodeProvider.php) because all three share the same functionality: retrieve an image from a 3rd party over HTTP. All three classes have constructors that allow you to tweak some settings and most, if not all, arguments should speak for themselves. If you're not sure which values are supported, click the links in this paragraph for documentation on the API's that are utilized by these classes.
+The default provider is the [`QRServerProvider`](lib/Providers/Qr/QRServerProvider.php) which uses the [goqr.me API](http://goqr.me/api/doc/create-qr-code/) to render QR-codes. Then we have the [`ImageChartsQRCodeProvider`](lib/Providers/Qr/ImageChartsQRCodeProvider.php) which uses the [image-charts.com replacement for Google Image Charts](https://image-charts.com) to render QR-codes and the [`QRicketProvider`](lib/Providers/Qr/QRicketProvider.php) which uses the [QRickit API](http://qrickit.com/qrickit_apps/qrickit_api.php). These three providers all inherit from a common (abstract) baseclass named [`BaseHTTPQRCodeProvider`](lib/Providers/Qr/BaseHTTPQRCodeProvider.php) because all three share the same functionality: retrieve an image from a 3rd party over HTTP. Finally, we have [`EndroidQrCodeProvider`](lib/Providers/Qr/EndroidQrCodeProvider.php), [`EndroidQrCodeWithLogoProvider`](lib/Providers/Qr/EndroidQrCodeWithLogoProvider.php) and [`BaconQrCodeProvider`](lib/Providers/Qr/BaconQrCodeProvider.php) which require an optional dependency to be installed to use (see Requirements section above), but will generate the QR codes locally. All five classes have constructors that allow you to tweak some settings and most, if not all, arguments should speak for themselves. If you're not sure which values are supported, click the links in this paragraph for documentation on the API's that are utilized by these classes.
If you don't like any of the built-in classes because you don't want to rely on external resources for example or because you're paranoid about sending the TOTP secret to these 3rd parties (which is useless to them since they miss *at least one* other factor in the [MFA process](http://en.wikipedia.org/wiki/Multi-factor_authentication)), feel tree to implement your own. The `IQRCodeProvider` interface couldn't be any simpler. All you need to do is implement 2 methods:
@@ -148,7 +158,7 @@
public function getMimeType() {
return 'image/png'; // This provider only returns PNG's
}
-
+
public function getQRCodeImage($qrtext, $size) {
ob_start(); // 'Catch' QRCode's output
QRCode::png($qrtext, null, QR_ECLEVEL_L, 3, 4); // We ignore $size and set it to 3
@@ -190,7 +200,7 @@
## Integrations
-- [CakePHP 3](https://github.com/andrej-griniuk/cakephp-two-factor-auth)
+- [CakePHP 3](https://github.com/andrej-griniuk/cakephp-two-factor-auth)
## License
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/composer.json
index 50f8b86..847b2f8 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/composer.json
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/composer.json
@@ -1,7 +1,7 @@
{
"name": "robthree/twofactorauth",
"description": "Two Factor Authentication",
- "version": "1.7.0",
+ "version": "1.8.0",
"type": "library",
"keywords": [ "Authentication", "Two Factor Authentication", "Multi Factor Authentication", "TFA", "MFA", "PHP", "Authenticator", "Authy" ],
"homepage": "https://github.com/RobThree/TwoFactorAuth",
@@ -21,7 +21,12 @@
"php": ">=5.6.0"
},
"require-dev": {
- "phpunit/phpunit": "@stable"
+ "phpunit/phpunit": "@stable",
+ "php-parallel-lint/php-parallel-lint": "^1.2"
+ },
+ "suggest": {
+ "bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider",
+ "endroid/qr-code": "Needed for EndroidQrCodeProvider"
},
"autoload": {
"psr-4": {
@@ -30,7 +35,15 @@
},
"autoload-dev": {
"psr-4": {
- "RobThree\\Auth\\Test\\": "tests"
+ "Tests\\": "tests/"
}
+ },
+ "scripts": {
+ "lint": [
+ "parallel-lint --exclude vendor ."
+ ],
+ "test": [
+ "XDEBUG_MODE=coverage phpunit"
+ ]
}
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/composer.lock b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/composer.lock
deleted file mode 100644
index 63df937..0000000
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/composer.lock
+++ /dev/null
@@ -1,980 +0,0 @@
-{
- "_readme": [
- "This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
- "This file is @generated automatically"
- ],
- "content-hash": "9647de85f54ba6db237f5ff42ff85a1f",
- "packages": [],
- "packages-dev": [
- {
- "name": "doctrine/instantiator",
- "version": "1.0.5",
- "source": {
- "type": "git",
- "url": "https://github.com/doctrine/instantiator.git",
- "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
- "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3,<8.0-DEV"
- },
- "require-dev": {
- "athletic/athletic": "~0.1.8",
- "ext-pdo": "*",
- "ext-phar": "*",
- "phpunit/phpunit": "~4.0",
- "squizlabs/php_codesniffer": "~2.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Marco Pivetta",
- "email": "ocramius@gmail.com",
- "homepage": "http://ocramius.github.com/"
- }
- ],
- "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
- "homepage": "https://github.com/doctrine/instantiator",
- "keywords": [
- "constructor",
- "instantiate"
- ],
- "time": "2015-06-14T21:17:01+00:00"
- },
- {
- "name": "phpdocumentor/reflection-docblock",
- "version": "2.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
- "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.0"
- },
- "suggest": {
- "dflydev/markdown": "~1.0",
- "erusev/parsedown": "~1.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.0.x-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "phpDocumentor": [
- "src/"
- ]
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Mike van Riel",
- "email": "mike.vanriel@naenius.com"
- }
- ],
- "time": "2015-02-03T12:10:50+00:00"
- },
- {
- "name": "phpspec/prophecy",
- "version": "v1.6.2",
- "source": {
- "type": "git",
- "url": "https://github.com/phpspec/prophecy.git",
- "reference": "6c52c2722f8460122f96f86346600e1077ce22cb"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb",
- "reference": "6c52c2722f8460122f96f86346600e1077ce22cb",
- "shasum": ""
- },
- "require": {
- "doctrine/instantiator": "^1.0.2",
- "php": "^5.3|^7.0",
- "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
- "sebastian/comparator": "^1.1",
- "sebastian/recursion-context": "^1.0|^2.0"
- },
- "require-dev": {
- "phpspec/phpspec": "^2.0",
- "phpunit/phpunit": "^4.8 || ^5.6.5"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.6.x-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Prophecy\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Konstantin Kudryashov",
- "email": "ever.zet@gmail.com",
- "homepage": "http://everzet.com"
- },
- {
- "name": "Marcello Duarte",
- "email": "marcello.duarte@gmail.com"
- }
- ],
- "description": "Highly opinionated mocking framework for PHP 5.3+",
- "homepage": "https://github.com/phpspec/prophecy",
- "keywords": [
- "Double",
- "Dummy",
- "fake",
- "mock",
- "spy",
- "stub"
- ],
- "time": "2016-11-21T14:58:47+00:00"
- },
- {
- "name": "phpunit/php-code-coverage",
- "version": "2.2.4",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
- "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3",
- "phpunit/php-file-iterator": "~1.3",
- "phpunit/php-text-template": "~1.2",
- "phpunit/php-token-stream": "~1.3",
- "sebastian/environment": "^1.3.2",
- "sebastian/version": "~1.0"
- },
- "require-dev": {
- "ext-xdebug": ">=2.1.4",
- "phpunit/phpunit": "~4"
- },
- "suggest": {
- "ext-dom": "*",
- "ext-xdebug": ">=2.2.1",
- "ext-xmlwriter": "*"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.2.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
- "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
- "keywords": [
- "coverage",
- "testing",
- "xunit"
- ],
- "time": "2015-10-06T15:47:00+00:00"
- },
- {
- "name": "phpunit/php-file-iterator",
- "version": "1.4.2",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
- "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.4.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "FilterIterator implementation that filters files based on a list of suffixes.",
- "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
- "keywords": [
- "filesystem",
- "iterator"
- ],
- "time": "2016-10-03T07:40:28+00:00"
- },
- {
- "name": "phpunit/php-text-template",
- "version": "1.2.1",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-text-template.git",
- "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
- "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Simple template engine.",
- "homepage": "https://github.com/sebastianbergmann/php-text-template/",
- "keywords": [
- "template"
- ],
- "time": "2015-06-21T13:50:34+00:00"
- },
- {
- "name": "phpunit/php-timer",
- "version": "1.0.8",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
- "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "phpunit/phpunit": "~4|~5"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "Utility class for timing",
- "homepage": "https://github.com/sebastianbergmann/php-timer/",
- "keywords": [
- "timer"
- ],
- "time": "2016-05-12T18:03:57+00:00"
- },
- {
- "name": "phpunit/php-token-stream",
- "version": "1.4.9",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-token-stream.git",
- "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b",
- "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b",
- "shasum": ""
- },
- "require": {
- "ext-tokenizer": "*",
- "php": ">=5.3.3"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.2"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.4-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Wrapper around PHP's tokenizer extension.",
- "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
- "keywords": [
- "tokenizer"
- ],
- "time": "2016-11-15T14:06:22+00:00"
- },
- {
- "name": "phpunit/phpunit",
- "version": "4.8.35",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87",
- "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87",
- "shasum": ""
- },
- "require": {
- "ext-dom": "*",
- "ext-json": "*",
- "ext-pcre": "*",
- "ext-reflection": "*",
- "ext-spl": "*",
- "php": ">=5.3.3",
- "phpspec/prophecy": "^1.3.1",
- "phpunit/php-code-coverage": "~2.1",
- "phpunit/php-file-iterator": "~1.4",
- "phpunit/php-text-template": "~1.2",
- "phpunit/php-timer": "^1.0.6",
- "phpunit/phpunit-mock-objects": "~2.3",
- "sebastian/comparator": "~1.2.2",
- "sebastian/diff": "~1.2",
- "sebastian/environment": "~1.3",
- "sebastian/exporter": "~1.2",
- "sebastian/global-state": "~1.0",
- "sebastian/version": "~1.0",
- "symfony/yaml": "~2.1|~3.0"
- },
- "suggest": {
- "phpunit/php-invoker": "~1.1"
- },
- "bin": [
- "phpunit"
- ],
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "4.8.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "The PHP Unit Testing framework.",
- "homepage": "https://phpunit.de/",
- "keywords": [
- "phpunit",
- "testing",
- "xunit"
- ],
- "time": "2017-02-06T05:18:07+00:00"
- },
- {
- "name": "phpunit/phpunit-mock-objects",
- "version": "2.3.8",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
- "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
- "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
- "shasum": ""
- },
- "require": {
- "doctrine/instantiator": "^1.0.2",
- "php": ">=5.3.3",
- "phpunit/php-text-template": "~1.2",
- "sebastian/exporter": "~1.2"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.4"
- },
- "suggest": {
- "ext-soap": "*"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.3.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "Mock Object library for PHPUnit",
- "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
- "keywords": [
- "mock",
- "xunit"
- ],
- "time": "2015-10-02T06:51:40+00:00"
- },
- {
- "name": "sebastian/comparator",
- "version": "1.2.4",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
- "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3",
- "sebastian/diff": "~1.2",
- "sebastian/exporter": "~1.2 || ~2.0"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.4"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.2.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Jeff Welch",
- "email": "whatthejeff@gmail.com"
- },
- {
- "name": "Volker Dusch",
- "email": "github@wallbash.com"
- },
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@2bepublished.at"
- },
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Provides the functionality to compare PHP values for equality",
- "homepage": "http://www.github.com/sebastianbergmann/comparator",
- "keywords": [
- "comparator",
- "compare",
- "equality"
- ],
- "time": "2017-01-29T09:50:25+00:00"
- },
- {
- "name": "sebastian/diff",
- "version": "1.4.1",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
- "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.8"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.4-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Kore Nordmann",
- "email": "mail@kore-nordmann.de"
- },
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Diff implementation",
- "homepage": "https://github.com/sebastianbergmann/diff",
- "keywords": [
- "diff"
- ],
- "time": "2015-12-08T07:14:41+00:00"
- },
- {
- "name": "sebastian/environment",
- "version": "1.3.8",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
- "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
- "shasum": ""
- },
- "require": {
- "php": "^5.3.3 || ^7.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^4.8 || ^5.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.3.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Provides functionality to handle HHVM/PHP environments",
- "homepage": "http://www.github.com/sebastianbergmann/environment",
- "keywords": [
- "Xdebug",
- "environment",
- "hhvm"
- ],
- "time": "2016-08-18T05:49:44+00:00"
- },
- {
- "name": "sebastian/exporter",
- "version": "1.2.2",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
- "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3",
- "sebastian/recursion-context": "~1.0"
- },
- "require-dev": {
- "ext-mbstring": "*",
- "phpunit/phpunit": "~4.4"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.3.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Jeff Welch",
- "email": "whatthejeff@gmail.com"
- },
- {
- "name": "Volker Dusch",
- "email": "github@wallbash.com"
- },
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@2bepublished.at"
- },
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
- {
- "name": "Adam Harvey",
- "email": "aharvey@php.net"
- }
- ],
- "description": "Provides the functionality to export PHP variables for visualization",
- "homepage": "http://www.github.com/sebastianbergmann/exporter",
- "keywords": [
- "export",
- "exporter"
- ],
- "time": "2016-06-17T09:04:28+00:00"
- },
- {
- "name": "sebastian/global-state",
- "version": "1.1.1",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
- "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.2"
- },
- "suggest": {
- "ext-uopz": "*"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Snapshotting of global state",
- "homepage": "http://www.github.com/sebastianbergmann/global-state",
- "keywords": [
- "global state"
- ],
- "time": "2015-10-12T03:26:01+00:00"
- },
- {
- "name": "sebastian/recursion-context",
- "version": "1.0.2",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "913401df809e99e4f47b27cdd781f4a258d58791"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
- "reference": "913401df809e99e4f47b27cdd781f4a258d58791",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.4"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Jeff Welch",
- "email": "whatthejeff@gmail.com"
- },
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
- {
- "name": "Adam Harvey",
- "email": "aharvey@php.net"
- }
- ],
- "description": "Provides functionality to recursively process PHP variables",
- "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
- "time": "2015-11-11T19:50:13+00:00"
- },
- {
- "name": "sebastian/version",
- "version": "1.0.6",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/version.git",
- "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
- "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
- "shasum": ""
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Library that helps with managing the version number of Git-hosted PHP projects",
- "homepage": "https://github.com/sebastianbergmann/version",
- "time": "2015-06-21T13:59:46+00:00"
- },
- {
- "name": "symfony/yaml",
- "version": "v2.8.17",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/yaml.git",
- "reference": "322a8c2dfbca15ad6b1b27e182899f98ec0e0153"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/322a8c2dfbca15ad6b1b27e182899f98ec0e0153",
- "reference": "322a8c2dfbca15ad6b1b27e182899f98ec0e0153",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Yaml\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Yaml Component",
- "homepage": "https://symfony.com",
- "time": "2017-01-21T16:40:50+00:00"
- }
- ],
- "aliases": [],
- "minimum-stability": "stable",
- "stability-flags": {
- "phpunit/phpunit": 0
- },
- "prefer-stable": false,
- "prefer-lowest": false,
- "platform": {
- "php": ">=5.3.0"
- },
- "platform-dev": []
-}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/BaconQrCodeProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/BaconQrCodeProvider.php
new file mode 100644
index 0000000..4d5cf01
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/BaconQrCodeProvider.php
@@ -0,0 +1,152 @@
+<?php
+
+namespace RobThree\Auth\Providers\Qr;
+
+use BaconQrCode\Writer;
+use BaconQrCode\Renderer\ImageRenderer;
+use BaconQrCode\Renderer\RendererStyle\RendererStyle;
+use BaconQrCode\Renderer\RendererStyle\Fill;
+use BaconQrCode\Renderer\Color\Rgb;
+use BaconQrCode\Renderer\RendererStyle\EyeFill;
+
+use BaconQrCode\Renderer\Image\EpsImageBackEnd;
+use BaconQrCode\Renderer\Image\ImageBackEndInterface;
+use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
+use BaconQrCode\Renderer\Image\SvgImageBackEnd;
+
+class BaconQrCodeProvider implements IQRCodeProvider
+{
+ private $borderWidth = 4; // default from Bacon QR Code
+ private $backgroundColour;
+ private $foregroundColour;
+ private $format;
+
+ /**
+ * Ensure we using the latest Bacon QR Code and specify default options
+ *
+ * @param int $borderWidth space around the QR code, 4 is the default from Bacon QR Code
+ * @param string $backgroundColour hex reference for the background colour
+ * @param string $foregroundColour hex reference for the foreground colour
+ * @param string $format the desired output, png or svg
+ */
+ public function __construct($borderWidth = 4, $backgroundColour = '#ffffff', $foregroundColour = '#000000', $format = 'png')
+ {
+ if (! class_exists(ImagickImageBackEnd::class)) {
+ throw new \RuntimeException('Make sure you are using version 2 of Bacon QR Code');
+ }
+
+ $this->borderWidth = $borderWidth;
+ $this->backgroundColour = $this->handleColour($backgroundColour);
+ $this->foregroundColour = $this->handleColour($foregroundColour);
+ $this->format = strtolower($format);
+ }
+
+ /**
+ * Standard functions from IQRCodeProvider
+ */
+
+ public function getMimeType()
+ {
+ switch ($this->format) {
+ case 'png':
+ return 'image/png';
+ case 'gif':
+ return 'image/gif';
+ case 'jpg':
+ case 'jpeg':
+ return 'image/jpeg';
+ case 'svg':
+ return 'image/svg+xml';
+ case 'eps':
+ return 'application/postscript';
+ }
+
+ throw new \RuntimeException(sprintf('Unknown MIME-type: %s', $this->format));
+ }
+
+ public function getQRCodeImage($qrText, $size)
+ {
+ switch ($this->format) {
+ case 'svg':
+ $backend = new SvgImageBackEnd;
+ break;
+ case 'eps':
+ $backend = new EpsImageBackEnd;
+ break;
+ default:
+ $backend = new ImagickImageBackEnd($this->format);
+ }
+
+ $output = $this->getQRCodeByBackend($qrText, $size, $backend);
+
+ if ($this->format == 'svg') {
+ $svg = explode("\n", $output);
+ return $svg[1];
+ }
+
+ return $output;
+ }
+
+ /**
+ * Abstract QR code generation function
+ * providing colour changing support
+ */
+ private function getQRCodeByBackend($qrText, $size, ImageBackEndInterface $backend)
+ {
+ $rendererStyleArgs = array($size, $this->borderWidth);
+
+ if (is_array($this->foregroundColour) && is_array($this->backgroundColour)) {
+ $rendererStyleArgs = array_merge($rendererStyleArgs, array(
+ null,
+ null,
+ Fill::withForegroundColor(
+ new Rgb(...$this->backgroundColour),
+ new Rgb(...$this->foregroundColour),
+ new EyeFill(null, null),
+ new EyeFill(null, null),
+ new EyeFill(null, null)
+ )
+ ));
+ }
+
+ $writer = new Writer(new ImageRenderer(
+ new RendererStyle(...$rendererStyleArgs),
+ $backend
+ ));
+
+ return $writer->writeString($qrText);
+ }
+
+ /**
+ * Ensure colour is an array of three values but also
+ * accept a string and assume its a 3 or 6 character hex
+ */
+ private function handleColour($colour)
+ {
+ if (is_string($colour) && $colour[0] == '#') {
+ $hexToRGB = function ($input) {
+ // split the array into three chunks
+ $split = str_split(trim($input, '#'), strlen($input) / 3);
+
+ // cope with three character hex reference
+ // three characters plus a # = 4
+ if (strlen($input) == 4) {
+ array_walk($split, function (&$character) {
+ $character = str_repeat($character, 2);
+ });
+ }
+
+ // convert hex to rgb
+ return array_map('hexdec', $split);
+ };
+
+ return $hexToRGB($colour);
+ }
+
+ if (is_array($colour) && count($colour) == 3) {
+ return $colour;
+ }
+
+ throw new \RuntimeException('Invalid colour value');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/BaseHTTPQRCodeProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/BaseHTTPQRCodeProvider.php
index 5cb3add..bcc8d56 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/BaseHTTPQRCodeProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/BaseHTTPQRCodeProvider.php
@@ -4,12 +4,18 @@
abstract class BaseHTTPQRCodeProvider implements IQRCodeProvider
{
+ /** @var bool */
protected $verifyssl;
+ /**
+ * @param string $url
+ *
+ * @return string|bool
+ */
protected function getContent($url)
{
$curlhandle = curl_init();
-
+
curl_setopt_array($curlhandle, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
@@ -20,8 +26,8 @@
CURLOPT_USERAGENT => 'TwoFactorAuth'
));
$data = curl_exec($curlhandle);
-
+
curl_close($curlhandle);
return $data;
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeProvider.php
new file mode 100755
index 0000000..810aa9b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeProvider.php
@@ -0,0 +1,70 @@
+<?php
+namespace RobThree\Auth\Providers\Qr;
+
+use Endroid\QrCode\ErrorCorrectionLevel;
+use Endroid\QrCode\QrCode;
+
+class EndroidQrCodeProvider implements IQRCodeProvider
+{
+ public $bgcolor;
+ public $color;
+ public $margin;
+ public $errorcorrectionlevel;
+
+ public function __construct($bgcolor = 'ffffff', $color = '000000', $margin = 0, $errorcorrectionlevel = 'H')
+ {
+ $this->bgcolor = $this->handleColor($bgcolor);
+ $this->color = $this->handleColor($color);
+ $this->margin = $margin;
+ $this->errorcorrectionlevel = $this->handleErrorCorrectionLevel($errorcorrectionlevel);
+ }
+
+ public function getMimeType()
+ {
+ return 'image/png';
+ }
+
+ public function getQRCodeImage($qrtext, $size)
+ {
+ return $this->qrCodeInstance($qrtext, $size)->writeString();
+ }
+
+ protected function qrCodeInstance($qrtext, $size)
+ {
+ $qrCode = new QrCode($qrtext);
+ $qrCode->setSize($size);
+
+ $qrCode->setErrorCorrectionLevel($this->errorcorrectionlevel);
+ $qrCode->setMargin($this->margin);
+ $qrCode->setBackgroundColor($this->bgcolor);
+ $qrCode->setForegroundColor($this->color);
+
+ return $qrCode;
+ }
+
+ private function handleColor($color)
+ {
+ $split = str_split($color, 2);
+ $r = hexdec($split[0]);
+ $g = hexdec($split[1]);
+ $b = hexdec($split[2]);
+
+ return ['r' => $r, 'g' => $g, 'b' => $b, 'a' => 0];
+ }
+
+ private function handleErrorCorrectionLevel($level)
+ {
+ switch ($level) {
+ case 'L':
+ return ErrorCorrectionLevel::LOW();
+ case 'M':
+ return ErrorCorrectionLevel::MEDIUM();
+ case 'Q':
+ return ErrorCorrectionLevel::QUARTILE();
+ case 'H':
+ return ErrorCorrectionLevel::HIGH();
+ default:
+ return ErrorCorrectionLevel::HIGH();
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeWithLogoProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeWithLogoProvider.php
new file mode 100755
index 0000000..ed8cc98
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeWithLogoProvider.php
@@ -0,0 +1,35 @@
+<?php
+namespace RobThree\Auth\Providers\Qr;
+
+use Endroid\QrCode\ErrorCorrectionLevel;
+use Endroid\QrCode\QrCode;
+
+class EndroidQrCodeWithLogoProvider extends EndroidQrCodeProvider
+{
+ protected $logoPath;
+ protected $logoSize;
+
+ /**
+ * Adds an image to the middle of the QR Code.
+ * @param string $path Path to an image file
+ * @param array|int $size Just the width, or [width, height]
+ */
+ public function setLogo($path, $size = null)
+ {
+ $this->logoPath = $path;
+ $this->logoSize = (array)$size;
+ }
+
+ protected function qrCodeInstance($qrtext, $size) {
+ $qrCode = parent::qrCodeInstance($qrtext, $size);
+
+ if ($this->logoPath) {
+ $qrCode->setLogoPath($this->logoPath);
+ if ($this->logoSize) {
+ $qrCode->setLogoSize($this->logoSize[0], $this->logoSize[1]);
+ }
+ }
+
+ return $qrCode;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/IQRCodeProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/IQRCodeProvider.php
index 83ed67b..e53a5ad 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/IQRCodeProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/IQRCodeProvider.php
@@ -4,6 +4,21 @@
interface IQRCodeProvider
{
+ /**
+ * Generate and return the QR code to embed in a web page
+ *
+ * @param string $qrtext the value to encode in the QR code
+ * @param int $size the desired size of the QR code
+ *
+ * @return string file contents of the QR code
+ */
public function getQRCodeImage($qrtext, $size);
+
+ /**
+ * Returns the appropriate mime type for the QR code
+ * that will be generated
+ *
+ * @return string
+ */
public function getMimeType();
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/ImageChartsQRCodeProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/ImageChartsQRCodeProvider.php
index cc094c3..ea46ed4 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/ImageChartsQRCodeProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/ImageChartsQRCodeProvider.php
@@ -3,37 +3,58 @@
namespace RobThree\Auth\Providers\Qr;
// https://image-charts.com
-class ImageChartsQRCodeProvider extends BaseHTTPQRCodeProvider
+class ImageChartsQRCodeProvider extends BaseHTTPQRCodeProvider
{
+ /** @var string */
public $errorcorrectionlevel;
+
+ /** @var int */
public $margin;
- function __construct($verifyssl = false, $errorcorrectionlevel = 'L', $margin = 1)
+ /**
+ * @param bool $verifyssl
+ * @param string $errorcorrectionlevel
+ * @param int $margin
+ */
+ public function __construct($verifyssl = false, $errorcorrectionlevel = 'L', $margin = 1)
{
- if (!is_bool($verifyssl))
- throw new \QRException('VerifySSL must be bool');
+ if (!is_bool($verifyssl)) {
+ throw new QRException('VerifySSL must be bool');
+ }
$this->verifyssl = $verifyssl;
-
+
$this->errorcorrectionlevel = $errorcorrectionlevel;
$this->margin = $margin;
}
-
- public function getMimeType()
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMimeType()
{
return 'image/png';
}
-
- public function getQRCodeImage($qrtext, $size)
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getQRCodeImage($qrtext, $size)
{
return $this->getContent($this->getUrl($qrtext, $size));
}
-
- public function getUrl($qrtext, $size)
+
+ /**
+ * @param string $qrtext the value to encode in the QR code
+ * @param int $size the desired size of the QR code
+ *
+ * @return string file contents of the QR code
+ */
+ public function getUrl($qrtext, $size)
{
return 'https://image-charts.com/chart?cht=qr'
- . '&chs=' . ceil($size/2) . 'x' . ceil($size/2)
+ . '&chs=' . ceil($size / 2) . 'x' . ceil($size / 2)
. '&chld=' . $this->errorcorrectionlevel . '|' . $this->margin
. '&chl=' . rawurlencode($qrtext);
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRException.php
index c28e829..4e75f77 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRException.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRException.php
@@ -1,5 +1,7 @@
<?php
+namespace RobThree\Auth\Providers\Qr;
+
use RobThree\Auth\TwoFactorAuthException;
-class QRException extends TwoFactorAuthException {}
\ No newline at end of file
+class QRException extends TwoFactorAuthException {}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRServerProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRServerProvider.php
index 928b87b..2252dfc 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRServerProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRServerProvider.php
@@ -3,22 +3,43 @@
namespace RobThree\Auth\Providers\Qr;
// http://goqr.me/api/doc/create-qr-code/
-class QRServerProvider extends BaseHTTPQRCodeProvider
+class QRServerProvider extends BaseHTTPQRCodeProvider
{
+ /** @var string */
public $errorcorrectionlevel;
+
+ /** @var int */
public $margin;
+
+ /** @var int */
public $qzone;
+
+ /** @var string */
public $bgcolor;
+
+ /** @var string */
public $color;
+
+ /** @var string */
public $format;
- function __construct($verifyssl = false, $errorcorrectionlevel = 'L', $margin = 4, $qzone = 1, $bgcolor = 'ffffff', $color = '000000', $format = 'png')
+ /**
+ * @param bool $verifyssl
+ * @param string $errorcorrectionlevel
+ * @param int $margin
+ * @param int $qzone
+ * @param string $bgcolor
+ * @param string $color
+ * @param string $format
+ */
+ public function __construct($verifyssl = false, $errorcorrectionlevel = 'L', $margin = 4, $qzone = 1, $bgcolor = 'ffffff', $color = '000000', $format = 'png')
{
- if (!is_bool($verifyssl))
+ if (!is_bool($verifyssl)) {
throw new QRException('VerifySSL must be bool');
+ }
$this->verifyssl = $verifyssl;
-
+
$this->errorcorrectionlevel = $errorcorrectionlevel;
$this->margin = $margin;
$this->qzone = $qzone;
@@ -26,37 +47,53 @@
$this->color = $color;
$this->format = $format;
}
-
- public function getMimeType()
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMimeType()
{
- switch (strtolower($this->format))
- {
- case 'png':
+ switch (strtolower($this->format)) {
+ case 'png':
return 'image/png';
- case 'gif':
+ case 'gif':
return 'image/gif';
- case 'jpg':
- case 'jpeg':
+ case 'jpg':
+ case 'jpeg':
return 'image/jpeg';
- case 'svg':
+ case 'svg':
return 'image/svg+xml';
- case 'eps':
+ case 'eps':
return 'application/postscript';
}
- throw new \QRException(sprintf('Unknown MIME-type: %s', $this->format));
+ throw new QRException(sprintf('Unknown MIME-type: %s', $this->format));
}
-
- public function getQRCodeImage($qrtext, $size)
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getQRCodeImage($qrtext, $size)
{
return $this->getContent($this->getUrl($qrtext, $size));
}
-
- private function decodeColor($value)
+
+ /**
+ * @param string $value
+ *
+ * @return string
+ */
+ private function decodeColor($value)
{
return vsprintf('%d-%d-%d', sscanf($value, "%02x%02x%02x"));
}
-
- public function getUrl($qrtext, $size)
+
+ /**
+ * @param string $qrtext the value to encode in the QR code
+ * @param int|string $size the desired size of the QR code
+ *
+ * @return string file contents of the QR code
+ */
+ public function getUrl($qrtext, $size)
{
return 'https://api.qrserver.com/v1/create-qr-code/'
. '?size=' . $size . 'x' . $size
@@ -68,4 +105,4 @@
. '&format=' . strtolower($this->format)
. '&data=' . rawurlencode($qrtext);
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRicketProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRicketProvider.php
index 59e27cc..166a8a9 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRicketProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Qr/QRicketProvider.php
@@ -3,45 +3,67 @@
namespace RobThree\Auth\Providers\Qr;
// http://qrickit.com/qrickit_apps/qrickit_api.php
-class QRicketProvider extends BaseHTTPQRCodeProvider
+class QRicketProvider extends BaseHTTPQRCodeProvider
{
+ /** @var string */
public $errorcorrectionlevel;
- public $margin;
- public $qzone;
+
+ /** @var string */
public $bgcolor;
+
+ /** @var string */
public $color;
+
+ /** @var string */
public $format;
- function __construct($errorcorrectionlevel = 'L', $bgcolor = 'ffffff', $color = '000000', $format = 'p')
+ /**
+ * @param string $errorcorrectionlevel
+ * @param string $bgcolor
+ * @param string $color
+ * @param string $format
+ */
+ public function __construct($errorcorrectionlevel = 'L', $bgcolor = 'ffffff', $color = '000000', $format = 'p')
{
$this->verifyssl = false;
-
+
$this->errorcorrectionlevel = $errorcorrectionlevel;
$this->bgcolor = $bgcolor;
$this->color = $color;
$this->format = $format;
}
-
- public function getMimeType()
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMimeType()
{
- switch (strtolower($this->format))
- {
- case 'p':
+ switch (strtolower($this->format)) {
+ case 'p':
return 'image/png';
- case 'g':
+ case 'g':
return 'image/gif';
- case 'j':
+ case 'j':
return 'image/jpeg';
}
- throw new \QRException(sprintf('Unknown MIME-type: %s', $this->format));
+ throw new QRException(sprintf('Unknown MIME-type: %s', $this->format));
}
-
- public function getQRCodeImage($qrtext, $size)
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getQRCodeImage($qrtext, $size)
{
return $this->getContent($this->getUrl($qrtext, $size));
}
-
- public function getUrl($qrtext, $size)
+
+ /**
+ * @param string $qrtext the value to encode in the QR code
+ * @param int|string $size the desired size of the QR code
+ *
+ * @return string file contents of the QR code
+ */
+ public function getUrl($qrtext, $size)
{
return 'http://qrickit.com/api/qr'
. '?qrsize=' . $size
@@ -51,4 +73,4 @@
. '&t=' . strtolower($this->format)
. '&d=' . rawurlencode($qrtext);
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/CSRNGProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/CSRNGProvider.php
index 8dba7fc..088edab 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/CSRNGProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/CSRNGProvider.php
@@ -4,11 +4,19 @@
class CSRNGProvider implements IRNGProvider
{
- public function getRandomBytes($bytecount) {
+ /**
+ * {@inheritdoc}
+ */
+ public function getRandomBytes($bytecount)
+ {
return random_bytes($bytecount); // PHP7+
}
-
- public function isCryptographicallySecure() {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isCryptographicallySecure()
+ {
return true;
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/HashRNGProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/HashRNGProvider.php
index eb42577..d17a5f8 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/HashRNGProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/HashRNGProvider.php
@@ -1,28 +1,43 @@
<?php
+
namespace RobThree\Auth\Providers\Rng;
class HashRNGProvider implements IRNGProvider
{
+ /** @var string */
private $algorithm;
-
- function __construct($algorithm = 'sha256' ) {
+
+ /**
+ * @param string $algorithm
+ */
+ public function __construct($algorithm = 'sha256')
+ {
$algos = array_values(hash_algos());
- if (!in_array($algorithm, $algos, true))
- throw new \RNGException('Unsupported algorithm specified');
+ if (!in_array($algorithm, $algos, true)) {
+ throw new RNGException('Unsupported algorithm specified');
+ }
$this->algorithm = $algorithm;
}
-
- public function getRandomBytes($bytecount) {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRandomBytes($bytecount)
+ {
$result = '';
$hash = mt_rand();
for ($i = 0; $i < $bytecount; $i++) {
- $hash = hash($this->algorithm, $hash.mt_rand(), true);
- $result .= $hash[mt_rand(0, strlen($hash)-1)];
+ $hash = hash($this->algorithm, $hash . mt_rand(), true);
+ $result .= $hash[mt_rand(0, strlen($hash) - 1)];
}
return $result;
}
-
- public function isCryptographicallySecure() {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isCryptographicallySecure()
+ {
return false;
}
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/IRNGProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/IRNGProvider.php
index 6be2800..e4e71c2 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/IRNGProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/IRNGProvider.php
@@ -4,6 +4,15 @@
interface IRNGProvider
{
+ /**
+ * @param int $bytecount the number of bytes of randomness to return
+ *
+ * @return string the random bytes
+ */
public function getRandomBytes($bytecount);
+
+ /**
+ * @return bool whether this provider is cryptographically secure
+ */
public function isCryptographicallySecure();
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/MCryptRNGProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/MCryptRNGProvider.php
index 0eeab2c..d1b6430 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/MCryptRNGProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/MCryptRNGProvider.php
@@ -4,20 +4,34 @@
class MCryptRNGProvider implements IRNGProvider
{
+ /** @var int */
private $source;
-
- function __construct($source = MCRYPT_DEV_URANDOM) {
+
+ /**
+ * @param int $source
+ */
+ public function __construct($source = MCRYPT_DEV_URANDOM)
+ {
$this->source = $source;
}
-
- public function getRandomBytes($bytecount) {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRandomBytes($bytecount)
+ {
$result = @mcrypt_create_iv($bytecount, $this->source);
- if ($result === false)
- throw new \RNGException('mcrypt_create_iv returned an invalid value');
+ if ($result === false) {
+ throw new RNGException('mcrypt_create_iv returned an invalid value');
+ }
return $result;
}
-
- public function isCryptographicallySecure() {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isCryptographicallySecure()
+ {
return true;
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/OpenSSLRNGProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/OpenSSLRNGProvider.php
index dc66c64..eb82b3b 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/OpenSSLRNGProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/OpenSSLRNGProvider.php
@@ -4,22 +4,37 @@
class OpenSSLRNGProvider implements IRNGProvider
{
+ /** @var bool */
private $requirestrong;
-
- function __construct($requirestrong = true) {
+
+ /**
+ * @param bool $requirestrong
+ */
+ public function __construct($requirestrong = true)
+ {
$this->requirestrong = $requirestrong;
}
-
- public function getRandomBytes($bytecount) {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRandomBytes($bytecount)
+ {
$result = openssl_random_pseudo_bytes($bytecount, $crypto_strong);
- if ($this->requirestrong && ($crypto_strong === false))
- throw new \RNGException('openssl_random_pseudo_bytes returned non-cryptographically strong value');
- if ($result === false)
- throw new \RNGException('openssl_random_pseudo_bytes returned an invalid value');
+ if ($this->requirestrong && ($crypto_strong === false)) {
+ throw new RNGException('openssl_random_pseudo_bytes returned non-cryptographically strong value');
+ }
+ if ($result === false) {
+ throw new RNGException('openssl_random_pseudo_bytes returned an invalid value');
+ }
return $result;
}
-
- public function isCryptographicallySecure() {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isCryptographicallySecure()
+ {
return $this->requirestrong;
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/RNGException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/RNGException.php
index eb5e913..f9a11ac 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/RNGException.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Rng/RNGException.php
@@ -1,5 +1,7 @@
<?php
+namespace RobThree\Auth\Providers\Rng;
+
use RobThree\Auth\TwoFactorAuthException;
-class RNGException extends TwoFactorAuthException {}
\ No newline at end of file
+class RNGException extends TwoFactorAuthException {}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/HttpTimeProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/HttpTimeProvider.php
index 8e7806e..c346e5a 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/HttpTimeProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/HttpTimeProvider.php
@@ -2,22 +2,33 @@
namespace RobThree\Auth\Providers\Time;
+use DateTime;
+
/**
* Takes the time from any webserver by doing a HEAD request on the specified URL and extracting the 'Date:' header
*/
class HttpTimeProvider implements ITimeProvider
{
+ /** @var string */
public $url;
- public $options;
+
+ /** @var string */
public $expectedtimeformat;
- function __construct($url = 'https://google.com', $expectedtimeformat = 'D, d M Y H:i:s O+', array $options = null)
+ /** @var array */
+ public $options;
+
+ /**
+ * @param string $url
+ * @param string $expectedtimeformat
+ * @param array $options
+ */
+ public function __construct($url = 'https://google.com', $expectedtimeformat = 'D, d M Y H:i:s O+', array $options = null)
{
$this->url = $url;
$this->expectedtimeformat = $expectedtimeformat;
- $this->options = $options;
- if ($this->options === null) {
- $this->options = array(
+ if ($options === null) {
+ $options = array(
'http' => array(
'method' => 'HEAD',
'follow_location' => false,
@@ -32,9 +43,14 @@
)
);
}
+ $this->options = $options;
}
- public function getTime() {
+ /**
+ * {@inheritdoc}
+ */
+ public function getTime()
+ {
try {
$context = stream_context_create($this->options);
$fd = fopen($this->url, 'rb', false, $context);
@@ -42,13 +58,14 @@
fclose($fd);
foreach ($headers['wrapper_data'] as $h) {
- if (strcasecmp(substr($h, 0, 5), 'Date:') === 0)
- return \DateTime::createFromFormat($this->expectedtimeformat, trim(substr($h,5)))->getTimestamp();
+ if (strcasecmp(substr($h, 0, 5), 'Date:') === 0) {
+ return DateTime::createFromFormat($this->expectedtimeformat, trim(substr($h, 5)))->getTimestamp();
+ }
}
- throw new \TimeException(sprintf('Unable to retrieve time from %s (Invalid or no "Date:" header found)', $this->url));
+ throw new \Exception('Invalid or no "Date:" header found');
+ } catch (\Exception $ex) {
+ throw new TimeException(sprintf('Unable to retrieve time from %s (%s)', $this->url, $ex->getMessage()));
}
- catch (Exception $ex) {
- throw new \TimeException(sprintf('Unable to retrieve time from %s (%s)', $this->url, $ex->getMessage()));
- }
+
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/ITimeProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/ITimeProvider.php
index a3b87a2..4799f17 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/ITimeProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/ITimeProvider.php
@@ -4,5 +4,8 @@
interface ITimeProvider
{
+ /**
+ * @return int the current timestamp according to this provider
+ */
public function getTime();
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/LocalMachineTimeProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/LocalMachineTimeProvider.php
index 572cedc..2fe6846 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/LocalMachineTimeProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/LocalMachineTimeProvider.php
@@ -2,8 +2,10 @@
namespace RobThree\Auth\Providers\Time;
-class LocalMachineTimeProvider implements ITimeProvider {
- public function getTime() {
+class LocalMachineTimeProvider implements ITimeProvider
+{
+ public function getTime()
+ {
return time();
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/NTPTimeProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/NTPTimeProvider.php
index d69a3a6..a701850 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/NTPTimeProvider.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/NTPTimeProvider.php
@@ -7,24 +7,40 @@
*/
class NTPTimeProvider implements ITimeProvider
{
+ /** @var string */
public $host;
+
+ /** @var int */
public $port;
+
+ /** @var int */
public $timeout;
- function __construct($host = 'time.google.com', $port = 123, $timeout = 1)
+ /**
+ * @param string $host
+ * @param int $port
+ * @param int $timeout
+ */
+ public function __construct($host = 'time.google.com', $port = 123, $timeout = 1)
{
$this->host = $host;
- if (!is_int($port) || $port <= 0 || $port > 65535)
- throw new \TimeException('Port must be 0 < port < 65535');
+ if (!is_int($port) || $port <= 0 || $port > 65535) {
+ throw new TimeException('Port must be 0 < port < 65535');
+ }
$this->port = $port;
- if (!is_int($timeout) || $timeout < 0)
- throw new \TimeException('Timeout must be >= 0');
+ if (!is_int($timeout) || $timeout < 0) {
+ throw new TimeException('Timeout must be >= 0');
+ }
$this->timeout = $timeout;
}
- public function getTime() {
+ /**
+ * {@inheritdoc}
+ */
+ public function getTime()
+ {
try {
/* Create a socket and connect to NTP server */
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
@@ -36,19 +52,19 @@
socket_send($sock, $msg, strlen($msg), 0);
/* Receive response and close socket */
- if (socket_recv($sock, $recv, 48, MSG_WAITALL) === false)
+ if (socket_recv($sock, $recv, 48, MSG_WAITALL) === false) {
throw new \Exception(socket_strerror(socket_last_error($sock)));
+ }
socket_close($sock);
/* Interpret response */
$data = unpack('N12', $recv);
- $timestamp = sprintf('%u', $data[9]);
+ $timestamp = (int) sprintf('%u', $data[9]);
/* NTP is number of seconds since 0000 UT on 1 January 1900 Unix time is seconds since 0000 UT on 1 January 1970 */
return $timestamp - 2208988800;
- }
- catch (Exception $ex) {
- throw new \TimeException(sprintf('Unable to retrieve time from %s (%s)', $this->host, $ex->getMessage()));
+ } catch (\Exception $ex) {
+ throw new TimeException(sprintf('Unable to retrieve time from %s (%s)', $this->host, $ex->getMessage()));
}
}
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/TimeException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/TimeException.php
index 8de544d..c5a06e2 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/TimeException.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/Providers/Time/TimeException.php
@@ -1,5 +1,7 @@
<?php
+namespace RobThree\Auth\Providers\Time;
+
use RobThree\Auth\TwoFactorAuthException;
-class TimeException extends TwoFactorAuthException {}
\ No newline at end of file
+class TimeException extends TwoFactorAuthException {}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/TwoFactorAuth.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/TwoFactorAuth.php
index 7bc067d..c46ac17 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/TwoFactorAuth.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/TwoFactorAuth.php
@@ -1,40 +1,82 @@
<?php
+
namespace RobThree\Auth;
use RobThree\Auth\Providers\Qr\IQRCodeProvider;
+use RobThree\Auth\Providers\Qr\QRServerProvider;
+use RobThree\Auth\Providers\Rng\CSRNGProvider;
+use RobThree\Auth\Providers\Rng\HashRNGProvider;
use RobThree\Auth\Providers\Rng\IRNGProvider;
+use RobThree\Auth\Providers\Rng\MCryptRNGProvider;
+use RobThree\Auth\Providers\Rng\OpenSSLRNGProvider;
+use RobThree\Auth\Providers\Time\HttpTimeProvider;
use RobThree\Auth\Providers\Time\ITimeProvider;
+use RobThree\Auth\Providers\Time\LocalMachineTimeProvider;
+use RobThree\Auth\Providers\Time\NTPTimeProvider;
// Based on / inspired by: https://github.com/PHPGangsta/GoogleAuthenticator
// Algorithms, digits, period etc. explained: https://github.com/google/google-authenticator/wiki/Key-Uri-Format
class TwoFactorAuth
{
+ /** @var string */
private $algorithm;
+
+ /** @var int */
private $period;
+
+ /** @var int */
private $digits;
+
+ /** @var string */
private $issuer;
+
+ /** @var ?IQRCodeProvider */
private $qrcodeprovider = null;
+
+ /** @var ?IRNGProvider */
private $rngprovider = null;
+
+ /** @var ?ITimeProvider */
private $timeprovider = null;
+
+ /** @var string */
private static $_base32dict = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=';
+
+ /** @var array */
private static $_base32;
+
+ /** @var array */
private static $_base32lookup = array();
+
+ /** @var array */
private static $_supportedalgos = array('sha1', 'sha256', 'sha512', 'md5');
- function __construct($issuer = null, $digits = 6, $period = 30, $algorithm = 'sha1', IQRCodeProvider $qrcodeprovider = null, IRNGProvider $rngprovider = null, ITimeProvider $timeprovider = null)
+ /**
+ * @param ?string $issuer
+ * @param int $digits
+ * @param int $period
+ * @param string $algorithm
+ * @param ?IQRCodeProvider $qrcodeprovider
+ * @param ?IRNGProvider $rngprovider
+ * @param ?ITimeProvider $timeprovider
+ */
+ public function __construct($issuer = null, $digits = 6, $period = 30, $algorithm = 'sha1', IQRCodeProvider $qrcodeprovider = null, IRNGProvider $rngprovider = null, ITimeProvider $timeprovider = null)
{
$this->issuer = $issuer;
- if (!is_int($digits) || $digits <= 0)
+ if (!is_int($digits) || $digits <= 0) {
throw new TwoFactorAuthException('Digits must be int > 0');
+ }
$this->digits = $digits;
- if (!is_int($period) || $period <= 0)
+ if (!is_int($period) || $period <= 0) {
throw new TwoFactorAuthException('Period must be int > 0');
+ }
$this->period = $period;
$algorithm = strtolower(trim($algorithm));
- if (!in_array($algorithm, self::$_supportedalgos))
+ if (!in_array($algorithm, self::$_supportedalgos)) {
throw new TwoFactorAuthException('Unsupported algorithm: ' . $algorithm);
+ }
$this->algorithm = $algorithm;
$this->qrcodeprovider = $qrcodeprovider;
$this->rngprovider = $rngprovider;
@@ -46,22 +88,34 @@
/**
* Create a new secret
+ *
+ * @param int $bits
+ * @param bool $requirecryptosecure
+ *
+ * @return string
*/
public function createSecret($bits = 80, $requirecryptosecure = true)
{
$secret = '';
- $bytes = ceil($bits / 5); //We use 5 bits of each byte (since we have a 32-character 'alphabet' / BASE32)
- $rngprovider = $this->getRngprovider();
- if ($requirecryptosecure && !$rngprovider->isCryptographicallySecure())
+ $bytes = (int) ceil($bits / 5); //We use 5 bits of each byte (since we have a 32-character 'alphabet' / BASE32)
+ $rngprovider = $this->getRngProvider();
+ if ($requirecryptosecure && !$rngprovider->isCryptographicallySecure()) {
throw new TwoFactorAuthException('RNG provider is not cryptographically secure');
+ }
$rnd = $rngprovider->getRandomBytes($bytes);
- for ($i = 0; $i < $bytes; $i++)
+ for ($i = 0; $i < $bytes; $i++) {
$secret .= self::$_base32[ord($rnd[$i]) & 31]; //Mask out left 3 bits for 0-31 values
+ }
return $secret;
}
/**
* Calculate the code with given secret and point in time
+ *
+ * @param string $secret
+ * @param ?int $time
+ *
+ * @return string
*/
public function getCode($secret, $time = null)
{
@@ -73,15 +127,23 @@
$value = unpack('N', $hashpart); // Unpack binary value
$value = $value[1] & 0x7FFFFFFF; // Drop MSB, keep only 31 bits
- return str_pad($value % pow(10, $this->digits), $this->digits, '0', STR_PAD_LEFT);
+ return str_pad((string) ($value % pow(10, $this->digits)), $this->digits, '0', STR_PAD_LEFT);
}
/**
* Check if the code is correct. This will accept codes starting from ($discrepancy * $period) sec ago to ($discrepancy * period) sec from now
+ *
+ * @param string $secret
+ * @param string $code
+ * @param int $discrepancy
+ * @param ?int $time
+ * @param int $timeslice
+ *
+ * @return bool
*/
public function verifyCode($secret, $code, $discrepancy = 1, $time = null, &$timeslice = 0)
{
- $timetamp = $this->getTime($time);
+ $timestamp = $this->getTime($time);
$timeslice = 0;
@@ -90,7 +152,7 @@
// of the match. Each iteration we either set the timeslice variable to the timeslice of the match
// or set the value to itself. This is an effort to maintain constant execution time for the code.
for ($i = -$discrepancy; $i <= $discrepancy; $i++) {
- $ts = $timetamp + ($i * $this->period);
+ $ts = $timestamp + ($i * $this->period);
$slice = $this->getTimeSlice($ts);
$timeslice = $this->codeEquals($this->getCode($secret, $ts), $code) ? $slice : $timeslice;
}
@@ -100,17 +162,24 @@
/**
* Timing-attack safe comparison of 2 codes (see http://blog.ircmaxell.com/2014/11/its-all-about-time.html)
+ *
+ * @param string $safe
+ * @param string $user
+ *
+ * @return bool
*/
- private function codeEquals($safe, $user) {
+ private function codeEquals($safe, $user)
+ {
if (function_exists('hash_equals')) {
return hash_equals($safe, $user);
}
// In general, it's not possible to prevent length leaks. So it's OK to leak the length. The important part is that
// we don't leak information about the difference of the two strings.
- if (strlen($safe)===strlen($user)) {
+ if (strlen($safe) === strlen($user)) {
$result = 0;
- for ($i = 0; $i < strlen($safe); $i++)
+ for ($i = 0; $i < strlen($safe); $i++) {
$result |= (ord($safe[$i]) ^ ord($user[$i]));
+ }
return $result === 0;
}
return false;
@@ -118,11 +187,18 @@
/**
* Get data-uri of QRCode
+ *
+ * @param string $label
+ * @param string $secret
+ * @param mixed $size
+ *
+ * @return string
*/
public function getQRCodeImageAsDataUri($label, $secret, $size = 200)
{
- if (!is_int($size) || $size <= 0)
+ if (!is_int($size) || $size <= 0) {
throw new TwoFactorAuthException('Size must be int > 0');
+ }
$qrcodeprovider = $this->getQrCodeProvider();
return 'data:'
@@ -133,37 +209,52 @@
/**
* Compare default timeprovider with specified timeproviders and ensure the time is within the specified number of seconds (leniency)
+ * @param ?array $timeproviders
+ * @param int $leniency
+ *
+ * @return void
*/
public function ensureCorrectTime(array $timeproviders = null, $leniency = 5)
{
- if ($timeproviders != null && !is_array($timeproviders))
- throw new TwoFactorAuthException('No timeproviders specified');
-
- if ($timeproviders == null)
+ if ($timeproviders === null) {
$timeproviders = array(
- new Providers\Time\NTPTimeProvider(),
- new Providers\Time\HttpTimeProvider()
+ new NTPTimeProvider(),
+ new HttpTimeProvider()
);
+ }
// Get default time provider
$timeprovider = $this->getTimeProvider();
// Iterate specified time providers
foreach ($timeproviders as $t) {
- if (!($t instanceof ITimeProvider))
+ if (!($t instanceof ITimeProvider)) {
throw new TwoFactorAuthException('Object does not implement ITimeProvider');
+ }
// Get time from default time provider and compare to specific time provider and throw if time difference is more than specified number of seconds leniency
- if (abs($timeprovider->getTime() - $t->getTime()) > $leniency)
+ if (abs($timeprovider->getTime() - $t->getTime()) > $leniency) {
throw new TwoFactorAuthException(sprintf('Time for timeprovider is off by more than %d seconds when compared to %s', $leniency, get_class($t)));
+ }
}
}
- private function getTime($time)
+ /**
+ * @param ?int $time
+ *
+ * @return int
+ */
+ private function getTime($time = null)
{
return ($time === null) ? $this->getTimeProvider()->getTime() : $time;
}
+ /**
+ * @param int $time
+ * @param int $offset
+ *
+ * @return int
+ */
private function getTimeSlice($time = null, $offset = 0)
{
return (int)floor($time / $this->period) + ($offset * $this->period);
@@ -171,6 +262,11 @@
/**
* Builds a string to be encoded in a QR code
+ *
+ * @param string $label
+ * @param string $secret
+ *
+ * @return string
*/
public function getQRText($label, $secret)
{
@@ -182,25 +278,33 @@
. '&digits=' . intval($this->digits);
}
+ /**
+ * @param string $value
+ * @return string
+ */
private function base32Decode($value)
{
- if (strlen($value)==0) return '';
+ if (strlen($value) == 0) {
+ return '';
+ }
- if (preg_match('/[^'.preg_quote(self::$_base32dict).']/', $value) !== 0)
+ if (preg_match('/[^' . preg_quote(self::$_base32dict) . ']/', $value) !== 0) {
throw new TwoFactorAuthException('Invalid base32 string');
+ }
$buffer = '';
- foreach (str_split($value) as $char)
- {
- if ($char !== '=')
- $buffer .= str_pad(decbin(self::$_base32lookup[$char]), 5, 0, STR_PAD_LEFT);
+ foreach (str_split($value) as $char) {
+ if ($char !== '=') {
+ $buffer .= str_pad(decbin(self::$_base32lookup[$char]), 5, '0', STR_PAD_LEFT);
+ }
}
$length = strlen($buffer);
$blocks = trim(chunk_split(substr($buffer, 0, $length - ($length % 8)), 8, ' '));
$output = '';
- foreach (explode(' ', $blocks) as $block)
- $output .= chr(bindec(str_pad($block, 8, 0, STR_PAD_RIGHT)));
+ foreach (explode(' ', $blocks) as $block) {
+ $output .= chr(bindec(str_pad($block, 8, '0', STR_PAD_RIGHT)));
+ }
return $output;
}
@@ -212,7 +316,7 @@
{
// Set default QR Code provider if none was specified
if (null === $this->qrcodeprovider) {
- return $this->qrcodeprovider = new Providers\Qr\QRServerProvider();
+ return $this->qrcodeprovider = new QRServerProvider();
}
return $this->qrcodeprovider;
}
@@ -221,22 +325,22 @@
* @return IRNGProvider
* @throws TwoFactorAuthException
*/
- public function getRngprovider()
+ public function getRngProvider()
{
if (null !== $this->rngprovider) {
return $this->rngprovider;
}
if (function_exists('random_bytes')) {
- return $this->rngprovider = new Providers\Rng\CSRNGProvider();
+ return $this->rngprovider = new CSRNGProvider();
}
if (function_exists('mcrypt_create_iv')) {
- return $this->rngprovider = new Providers\Rng\MCryptRNGProvider();
+ return $this->rngprovider = new MCryptRNGProvider();
}
if (function_exists('openssl_random_pseudo_bytes')) {
- return $this->rngprovider = new Providers\Rng\OpenSSLRNGProvider();
+ return $this->rngprovider = new OpenSSLRNGProvider();
}
if (function_exists('hash')) {
- return $this->rngprovider = new Providers\Rng\HashRNGProvider();
+ return $this->rngprovider = new HashRNGProvider();
}
throw new TwoFactorAuthException('Unable to find a suited RNGProvider');
}
@@ -249,8 +353,8 @@
{
// Set default time provider if none was specified
if (null === $this->timeprovider) {
- return $this->timeprovider = new Providers\Time\LocalMachineTimeProvider();
+ return $this->timeprovider = new LocalMachineTimeProvider();
}
return $this->timeprovider;
}
-}
\ No newline at end of file
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/TwoFactorAuthException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/TwoFactorAuthException.php
index af51b74..bce8370 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/TwoFactorAuthException.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/lib/TwoFactorAuthException.php
@@ -4,4 +4,4 @@
use Exception;
-class TwoFactorAuthException extends \Exception {}
\ No newline at end of file
+class TwoFactorAuthException extends Exception {}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/phpunit.xml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/phpunit.xml
index 92c3a27..b2ff004 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/phpunit.xml
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/phpunit.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
@@ -6,15 +6,21 @@
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
+ xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
stopOnFailure="false">
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
- <filter>
- <whitelist processUncoveredFilesFromWhitelist="true">
+ <coverage processUncoveredFiles="true">
+ <include>
<directory suffix=".php">./lib</directory>
- </whitelist>
- </filter>
-</phpunit>
\ No newline at end of file
+ </include>
+ <report>
+ <html outputDirectory="build/coverage"/>
+ <text outputFile="php://stdout"/>
+ </report>
+ </coverage>
+</phpunit>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/MightNotMakeAssertions.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/MightNotMakeAssertions.php
new file mode 100644
index 0000000..a7fbded
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/MightNotMakeAssertions.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Tests;
+
+trait MightNotMakeAssertions
+{
+ /**
+ * This is a shim to support PHPUnit for php 5.6 and 7.0.
+ *
+ * It has to be named something that doesn't collide with existing
+ * TestCase methods as we can't support PHP return types right now
+ *
+ * @return void
+ */
+ public function noAssertionsMade()
+ {
+ foreach (class_parents($this) as $parent) {
+ if (method_exists($parent, 'expectNotToPerformAssertions')) {
+ parent::expectNotToPerformAssertions();
+ return;
+ }
+ }
+
+ $this->assertTrue(true);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Qr/IQRCodeProviderTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Qr/IQRCodeProviderTest.php
new file mode 100644
index 0000000..86dd431
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Qr/IQRCodeProviderTest.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Tests\Providers\Qr;
+
+use PHPUnit\Framework\TestCase;
+use RobThree\Auth\TwoFactorAuth;
+use RobThree\Auth\TwoFactorAuthException;
+
+class IQRCodeProviderTest extends TestCase
+{
+ /**
+ * @param string $datauri
+ *
+ * @return null|array
+ */
+ private function DecodeDataUri($datauri)
+ {
+ if (preg_match('/data:(?P<mimetype>[\w\.\-\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
+ return array(
+ 'mimetype' => $m['mimetype'],
+ 'encoding' => $m['encoding'],
+ 'data' => base64_decode($m['data'])
+ );
+ }
+
+ return null;
+ }
+
+ /**
+ * @return void
+ */
+ public function testTotpUriIsCorrect()
+ {
+ $qr = new TestQrProvider();
+
+ $tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr);
+ $data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
+ $this->assertEquals('test/test', $data['mimetype']);
+ $this->assertEquals('base64', $data['encoding']);
+ $this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=Test%26Issuer&period=30&algorithm=SHA1&digits=6@200', $data['data']);
+ }
+
+ /**
+ * @return void
+ */
+ public function testGetQRCodeImageAsDataUriThrowsOnInvalidSize()
+ {
+ $qr = new TestQrProvider();
+
+ $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', $qr);
+
+ $this->expectException(TwoFactorAuthException::class);
+
+ $tfa->getQRCodeImageAsDataUri('Test', 'VMR466AB62ZBOKHE', 0);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Qr/TestQrProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Qr/TestQrProvider.php
new file mode 100644
index 0000000..93242c2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Qr/TestQrProvider.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Tests\Providers\Qr;
+
+use RobThree\Auth\Providers\Qr\IQRCodeProvider;
+
+class TestQrProvider implements IQRCodeProvider
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function getQRCodeImage($qrtext, $size)
+ {
+ return $qrtext . '@' . $size;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMimeType()
+ {
+ return 'test/test';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/CSRNGProviderTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/CSRNGProviderTest.php
new file mode 100644
index 0000000..e42ccfd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/CSRNGProviderTest.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Tests\Providers\Rng;
+
+use PHPUnit\Framework\TestCase;
+use Tests\MightNotMakeAssertions;
+use RobThree\Auth\Providers\Rng\CSRNGProvider;
+
+class CSRNGProviderTest extends TestCase
+{
+ use NeedsRngLengths, MightNotMakeAssertions;
+
+ /**
+ * @requires function random_bytes
+ *
+ * @return void
+ */
+ public function testCSRNGProvidersReturnExpectedNumberOfBytes()
+ {
+ if (function_exists('random_bytes')) {
+ $rng = new CSRNGProvider();
+ foreach ($this->rngTestLengths as $l) {
+ $this->assertEquals($l, strlen($rng->getRandomBytes($l)));
+ }
+ $this->assertTrue($rng->isCryptographicallySecure());
+ } else {
+ $this->noAssertionsMade();
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/HashRNGProviderTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/HashRNGProviderTest.php
new file mode 100644
index 0000000..c99879d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/HashRNGProviderTest.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Tests\Providers\Rng;
+
+use PHPUnit\Framework\TestCase;
+use RobThree\Auth\Providers\Rng\HashRNGProvider;
+
+class HashRNGProviderTest extends TestCase
+{
+ use NeedsRngLengths;
+
+ /**
+ * @return void
+ */
+ public function testHashRNGProvidersReturnExpectedNumberOfBytes()
+ {
+ $rng = new HashRNGProvider();
+ foreach ($this->rngTestLengths as $l) {
+ $this->assertEquals($l, strlen($rng->getRandomBytes($l)));
+ }
+
+ $this->assertFalse($rng->isCryptographicallySecure());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/IRNGProviderTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/IRNGProviderTest.php
new file mode 100644
index 0000000..8897673
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/IRNGProviderTest.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Tests\Providers\Rng;
+
+use PHPUnit\Framework\TestCase;
+use RobThree\Auth\TwoFactorAuth;
+use RobThree\Auth\TwoFactorAuthException;
+
+class IRNGProviderTest extends TestCase
+{
+ /**
+ * @return void
+ */
+ public function testCreateSecretThrowsOnInsecureRNGProvider()
+ {
+ $rng = new TestRNGProvider();
+
+ $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
+
+ $this->expectException(TwoFactorAuthException::class);
+ $tfa->createSecret();
+ }
+
+ /**
+ * @return void
+ */
+ public function testCreateSecretOverrideSecureDoesNotThrowOnInsecureRNG()
+ {
+ $rng = new TestRNGProvider();
+
+ $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
+ $this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret(80, false));
+ }
+
+ /**
+ * @return void
+ */
+ public function testCreateSecretDoesNotThrowOnSecureRNGProvider()
+ {
+ $rng = new TestRNGProvider(true);
+
+ $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
+ $this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret());
+ }
+
+ /**
+ * @return void
+ */
+ public function testCreateSecretGeneratesDesiredAmountOfEntropy()
+ {
+ $rng = new TestRNGProvider(true);
+
+ $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
+ $this->assertEquals('A', $tfa->createSecret(5));
+ $this->assertEquals('AB', $tfa->createSecret(6));
+ $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $tfa->createSecret(128));
+ $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(160));
+ $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(320));
+ $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567A', $tfa->createSecret(321));
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/MCryptRNGProviderTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/MCryptRNGProviderTest.php
new file mode 100644
index 0000000..f6dd91e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/MCryptRNGProviderTest.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Tests\Providers\Rng;
+
+use PHPUnit\Framework\TestCase;
+use Tests\MightNotMakeAssertions;
+use RobThree\Auth\Providers\Rng\MCryptRNGProvider;
+
+class MCryptRNGProviderTest extends TestCase
+{
+ use NeedsRngLengths, MightNotMakeAssertions;
+
+ /**
+ * @requires function mcrypt_create_iv
+ *
+ * @return void
+ */
+ public function testMCryptRNGProvidersReturnExpectedNumberOfBytes()
+ {
+ if (function_exists('mcrypt_create_iv')) {
+ $rng = new MCryptRNGProvider();
+
+ foreach ($this->rngTestLengths as $l) {
+ $this->assertEquals($l, strlen($rng->getRandomBytes($l)));
+ }
+
+ $this->assertTrue($rng->isCryptographicallySecure());
+ } else {
+ $this->noAssertionsMade();
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/NeedsRngLengths.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/NeedsRngLengths.php
new file mode 100644
index 0000000..7bbfed9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/NeedsRngLengths.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Tests\Providers\Rng;
+
+trait NeedsRngLengths
+{
+ /** @var array */
+ protected $rngTestLengths = array(1, 16, 32, 256);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/OpenSSLRNGProviderTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/OpenSSLRNGProviderTest.php
new file mode 100644
index 0000000..c941fcc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/OpenSSLRNGProviderTest.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Tests\Providers\Rng;
+
+use PHPUnit\Framework\TestCase;
+use RobThree\Auth\Providers\Rng\OpenSSLRNGProvider;
+
+class OpenSSLRNGProviderTest extends TestCase
+{
+ use NeedsRngLengths;
+
+ /**
+ * @return void
+ */
+ public function testStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes()
+ {
+ $rng = new OpenSSLRNGProvider(true);
+ foreach ($this->rngTestLengths as $l) {
+ $this->assertEquals($l, strlen($rng->getRandomBytes($l)));
+ }
+
+ $this->assertTrue($rng->isCryptographicallySecure());
+ }
+
+ /**
+ * @return void
+ */
+ public function testNonStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes()
+ {
+ $rng = new OpenSSLRNGProvider(false);
+ foreach ($this->rngTestLengths as $l) {
+ $this->assertEquals($l, strlen($rng->getRandomBytes($l)));
+ }
+
+ $this->assertFalse($rng->isCryptographicallySecure());
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/TestRNGProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/TestRNGProvider.php
new file mode 100644
index 0000000..7179521
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Rng/TestRNGProvider.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Tests\Providers\Rng;
+
+use RobThree\Auth\Providers\Rng\IRNGProvider;
+
+class TestRNGProvider implements IRNGProvider
+{
+ /** @var bool */
+ private $isSecure;
+
+ /**
+ * @param bool $isSecure whether this provider is cryptographically secure
+ */
+ function __construct($isSecure = false)
+ {
+ $this->isSecure = $isSecure;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRandomBytes($bytecount)
+ {
+ $result = '';
+
+ for ($i = 0; $i < $bytecount; $i++) {
+ $result .= chr($i);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isCryptographicallySecure()
+ {
+ return $this->isSecure;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Time/ITimeProviderTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Time/ITimeProviderTest.php
new file mode 100644
index 0000000..159e0c8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Time/ITimeProviderTest.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Tests\Providers\Time;
+
+use PHPUnit\Framework\TestCase;
+use Tests\MightNotMakeAssertions;
+use RobThree\Auth\TwoFactorAuthException;
+use RobThree\Auth\TwoFactorAuth;
+
+class ITimeProviderTest extends TestCase
+{
+ use MightNotMakeAssertions;
+
+ /**
+ * @return void
+ */
+ public function testEnsureCorrectTimeDoesNotThrowForCorrectTime()
+ {
+ $tpr1 = new TestTimeProvider(123);
+ $tpr2 = new TestTimeProvider(128);
+
+ $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1);
+ $tfa->ensureCorrectTime(array($tpr2)); // 128 - 123 = 5 => within default leniency
+
+ $this->noAssertionsMade();
+ }
+
+ /**
+ * @return void
+ */
+ public function testEnsureCorrectTimeThrowsOnIncorrectTime()
+ {
+ $tpr1 = new TestTimeProvider(123);
+ $tpr2 = new TestTimeProvider(124);
+
+ $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1);
+
+ $this->expectException(TwoFactorAuthException::class);
+
+ $tfa->ensureCorrectTime(array($tpr2), 0); // We force a leniency of 0, 124-123 = 1 so this should throw
+ }
+
+ /**
+ * @return void
+ */
+ public function testEnsureDefaultTimeProviderReturnsCorrectTime()
+ {
+ $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1');
+ $tfa->ensureCorrectTime(array(new TestTimeProvider(time())), 1); // Use a leniency of 1, should the time change between both time() calls
+
+ $this->noAssertionsMade();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Time/TestTimeProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Time/TestTimeProvider.php
new file mode 100644
index 0000000..0fc2d12
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/Providers/Time/TestTimeProvider.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Tests\Providers\Time;
+
+use RobThree\Auth\Providers\Time\ITimeProvider;
+
+class TestTimeProvider implements ITimeProvider
+{
+ /** @var int */
+ private $time;
+
+ /**
+ * @param int $time
+ */
+ function __construct($time)
+ {
+ $this->time = $time;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getTime()
+ {
+ return $this->time;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/TwoFactorAuthTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/TwoFactorAuthTest.php
index a0f2f67..ca00df9 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/TwoFactorAuthTest.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/robthree/twofactorauth/tests/TwoFactorAuthTest.php
@@ -1,218 +1,151 @@
<?php
-require_once 'lib/TwoFactorAuth.php';
-require_once 'lib/TwoFactorAuthException.php';
-require_once 'lib/Providers/Qr/IQRCodeProvider.php';
-require_once 'lib/Providers/Qr/BaseHTTPQRCodeProvider.php';
-require_once 'lib/Providers/Qr/ImageChartsQRCodeProvider.php';
-require_once 'lib/Providers/Qr/QRException.php';
+namespace Tests;
-require_once 'lib/Providers/Rng/IRNGProvider.php';
-require_once 'lib/Providers/Rng/RNGException.php';
-require_once 'lib/Providers/Rng/CSRNGProvider.php';
-require_once 'lib/Providers/Rng/MCryptRNGProvider.php';
-require_once 'lib/Providers/Rng/OpenSSLRNGProvider.php';
-require_once 'lib/Providers/Rng/HashRNGProvider.php';
-require_once 'lib/Providers/Rng/RNGException.php';
-
-require_once 'lib/Providers/Time/ITimeProvider.php';
-require_once 'lib/Providers/Time/LocalMachineTimeProvider.php';
-require_once 'lib/Providers/Time/HttpTimeProvider.php';
-require_once 'lib/Providers/Time/NTPTimeProvider.php';
-require_once 'lib/Providers/Time/TimeException.php';
-
+use PHPUnit\Framework\TestCase;
+use RobThree\Auth\TwoFactorAuthException;
use RobThree\Auth\TwoFactorAuth;
-use RobThree\Auth\Providers\Qr\IQRCodeProvider;
-use RobThree\Auth\Providers\Rng\IRNGProvider;
-use RobThree\Auth\Providers\Time\ITimeProvider;
-
-class TwoFactorAuthTest extends PHPUnit_Framework_TestCase
+class TwoFactorAuthTest extends TestCase
{
+ use MightNotMakeAssertions;
+
/**
- * @expectedException \RobThree\Auth\TwoFactorAuthException
+ * @return void
*/
- public function testConstructorThrowsOnInvalidDigits() {
+ public function testConstructorThrowsOnInvalidDigits()
+ {
+ $this->expectException(TwoFactorAuthException::class);
new TwoFactorAuth('Test', 0);
}
/**
- * @expectedException \RobThree\Auth\TwoFactorAuthException
+ * @return void
*/
- public function testConstructorThrowsOnInvalidPeriod() {
+ public function testConstructorThrowsOnInvalidPeriod()
+ {
+ $this->expectException(TwoFactorAuthException::class);
new TwoFactorAuth('Test', 6, 0);
}
/**
- * @expectedException \RobThree\Auth\TwoFactorAuthException
+ * @return void
*/
- public function testConstructorThrowsOnInvalidAlgorithm() {
+ public function testConstructorThrowsOnInvalidAlgorithm()
+ {
+ $this->expectException(TwoFactorAuthException::class);
new TwoFactorAuth('Test', 6, 30, 'xxx');
}
- public function testGetCodeReturnsCorrectResults() {
-
+ /**
+ * @return void
+ */
+ public function testGetCodeReturnsCorrectResults()
+ {
$tfa = new TwoFactorAuth('Test');
$this->assertEquals('543160', $tfa->getCode('VMR466AB62ZBOKHE', 1426847216));
$this->assertEquals('538532', $tfa->getCode('VMR466AB62ZBOKHE', 0));
}
/**
- * @expectedException \RobThree\Auth\TwoFactorAuthException
+ * @return void
*/
- public function testCreateSecretThrowsOnInsecureRNGProvider() {
- $rng = new TestRNGProvider();
-
- $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
- $tfa->createSecret();
- }
-
- public function testCreateSecretOverrideSecureDoesNotThrowOnInsecureRNG() {
- $rng = new TestRNGProvider();
-
- $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
- $this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret(80, false));
- }
-
- public function testCreateSecretDoesNotThrowOnSecureRNGProvider() {
- $rng = new TestRNGProvider(true);
-
- $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
- $this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret());
- }
-
- public function testCreateSecretGeneratesDesiredAmountOfEntropy() {
- $rng = new TestRNGProvider(true);
-
- $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
- $this->assertEquals('A', $tfa->createSecret(5));
- $this->assertEquals('AB', $tfa->createSecret(6));
- $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $tfa->createSecret(128));
- $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(160));
- $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(320));
- $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567A', $tfa->createSecret(321));
- }
-
- public function testEnsureCorrectTimeDoesNotThrowForCorrectTime() {
- $tpr1 = new TestTimeProvider(123);
- $tpr2 = new TestTimeProvider(128);
-
- $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1);
- $tfa->ensureCorrectTime(array($tpr2)); // 128 - 123 = 5 => within default leniency
+ public function testEnsureAllTimeProvidersReturnCorrectTime()
+ {
+ $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1');
+ $tfa->ensureCorrectTime(array(
+ new \RobThree\Auth\Providers\Time\NTPTimeProvider(), // Uses pool.ntp.org by default
+ //new \RobThree\Auth\Providers\Time\NTPTimeProvider('time.google.com'), // Somehow time.google.com and time.windows.com make travis timeout??
+ new \RobThree\Auth\Providers\Time\HttpTimeProvider(), // Uses google.com by default
+ new \RobThree\Auth\Providers\Time\HttpTimeProvider('https://github.com'),
+ new \RobThree\Auth\Providers\Time\HttpTimeProvider('https://yahoo.com'),
+ ));
+ $this->noAssertionsMade();
}
/**
- * @expectedException \RobThree\Auth\TwoFactorAuthException
+ * @return void
*/
- public function testEnsureCorrectTimeThrowsOnIncorrectTime() {
- $tpr1 = new TestTimeProvider(123);
- $tpr2 = new TestTimeProvider(124);
-
- $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1);
- $tfa->ensureCorrectTime(array($tpr2), 0); // We force a leniency of 0, 124-123 = 1 so this should throw
- }
-
-
- public function testEnsureDefaultTimeProviderReturnsCorrectTime() {
- $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1');
- $tfa->ensureCorrectTime(array(new TestTimeProvider(time())), 1); // Use a leniency of 1, should the time change between both time() calls
- }
-
- public function testEnsureAllTimeProvidersReturnCorrectTime() {
- $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1');
- $tfa->ensureCorrectTime(array(
- new RobThree\Auth\Providers\Time\NTPTimeProvider(), // Uses pool.ntp.org by default
- //new RobThree\Auth\Providers\Time\NTPTimeProvider('time.google.com'), // Somehow time.google.com and time.windows.com make travis timeout??
- new RobThree\Auth\Providers\Time\HttpTimeProvider(), // Uses google.com by default
- new RobThree\Auth\Providers\Time\HttpTimeProvider('https://github.com'),
- new RobThree\Auth\Providers\Time\HttpTimeProvider('https://yahoo.com'),
- ));
- }
-
- public function testVerifyCodeWorksCorrectly() {
-
+ public function testVerifyCodeWorksCorrectly()
+ {
$tfa = new TwoFactorAuth('Test', 6, 30);
- $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847190));
- $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 29)); //Test discrepancy
- $this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 30)); //Test discrepancy
- $this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 - 1)); //Test discrepancy
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847190));
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 29)); //Test discrepancy
+ $this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 30)); //Test discrepancy
+ $this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 - 1)); //Test discrepancy
- $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 0)); //Test discrepancy
- $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 35)); //Test discrepancy
- $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 35)); //Test discrepancy
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 0)); //Test discrepancy
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 35)); //Test discrepancy
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 35)); //Test discrepancy
- $this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 65)); //Test discrepancy
- $this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 65)); //Test discrepancy
+ $this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 65)); //Test discrepancy
+ $this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 65)); //Test discrepancy
- $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 + 65)); //Test discrepancy
- $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 - 65)); //Test discrepancy
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 + 65)); //Test discrepancy
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 - 65)); //Test discrepancy
}
- public function testVerifyCorrectTimeSliceIsReturned() {
+ /**
+ * @return void
+ */
+ public function testVerifyCorrectTimeSliceIsReturned()
+ {
$tfa = new TwoFactorAuth('Test', 6, 30);
// We test with discrepancy 3 (so total of 7 codes: c-3, c-2, c-1, c, c+1, c+2, c+3
// Ensure each corresponding timeslice is returned correctly
- $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '534113', 3, 1426847190, $timeslice1));
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '534113', 3, 1426847190, $timeslice1));
$this->assertEquals(47561570, $timeslice1);
- $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '819652', 3, 1426847190, $timeslice2));
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '819652', 3, 1426847190, $timeslice2));
$this->assertEquals(47561571, $timeslice2);
- $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '915954', 3, 1426847190, $timeslice3));
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '915954', 3, 1426847190, $timeslice3));
$this->assertEquals(47561572, $timeslice3);
- $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 3, 1426847190, $timeslice4));
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 3, 1426847190, $timeslice4));
$this->assertEquals(47561573, $timeslice4);
- $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '348401', 3, 1426847190, $timeslice5));
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '348401', 3, 1426847190, $timeslice5));
$this->assertEquals(47561574, $timeslice5);
- $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '648525', 3, 1426847190, $timeslice6));
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '648525', 3, 1426847190, $timeslice6));
$this->assertEquals(47561575, $timeslice6);
- $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '170645', 3, 1426847190, $timeslice7));
+ $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '170645', 3, 1426847190, $timeslice7));
$this->assertEquals(47561576, $timeslice7);
// Incorrect code should return false and a 0 timeslice
- $this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '111111', 3, 1426847190, $timeslice8));
+ $this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '111111', 3, 1426847190, $timeslice8));
$this->assertEquals(0, $timeslice8);
}
- public function testTotpUriIsCorrect() {
- $qr = new TestQrProvider();
-
- $tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr);
- $data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
- $this->assertEquals('test/test', $data['mimetype']);
- $this->assertEquals('base64', $data['encoding']);
- $this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=Test%26Issuer&period=30&algorithm=SHA1&digits=6@200', $data['data']);
- }
-
/**
- * @expectedException \RobThree\Auth\TwoFactorAuthException
+ * @return void
*/
- public function testGetQRCodeImageAsDataUriThrowsOnInvalidSize() {
- $qr = new TestQrProvider();
-
- $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', $qr);
- $tfa->getQRCodeImageAsDataUri('Test', 'VMR466AB62ZBOKHE', 0);
- }
-
- /**
- * @expectedException \RobThree\Auth\TwoFactorAuthException
- */
- public function testGetCodeThrowsOnInvalidBase32String1() {
+ public function testGetCodeThrowsOnInvalidBase32String1()
+ {
$tfa = new TwoFactorAuth('Test');
+
+ $this->expectException(TwoFactorAuthException::class);
+
$tfa->getCode('FOO1BAR8BAZ9'); //1, 8 & 9 are invalid chars
}
/**
- * @expectedException \RobThree\Auth\TwoFactorAuthException
+ * @return void
*/
- public function testGetCodeThrowsOnInvalidBase32String2() {
+ public function testGetCodeThrowsOnInvalidBase32String2()
+ {
$tfa = new TwoFactorAuth('Test');
+
+ $this->expectException(TwoFactorAuthException::class);
+
$tfa->getCode('mzxw6==='); //Lowercase
}
- public function testKnownBase32DecodeTestVectors() {
+ /**
+ * @return void
+ */
+ public function testKnownBase32DecodeTestVectors()
+ {
// We usually don't test internals (e.g. privates) but since we rely heavily on base32 decoding and don't want
// to expose this method nor do we want to give people the possibility of implementing / providing their own base32
// decoding/decoder (as we do with Rng/QR providers for example) we simply test the private base32Decode() method
@@ -226,7 +159,7 @@
// Dave Thomas and Andy Hunt -- "Pragmatic Unit Testing
$tfa = new TwoFactorAuth('Test');
- $method = new ReflectionMethod('RobThree\Auth\TwoFactorAuth', 'base32Decode');
+ $method = new \ReflectionMethod(TwoFactorAuth::class, 'base32Decode');
$method->setAccessible(true);
// Test vectors from: https://tools.ietf.org/html/rfc4648#page-12
@@ -239,14 +172,18 @@
$this->assertEquals('foobar', $method->invoke($tfa, 'MZXW6YTBOI======'));
}
- public function testKnownBase32DecodeUnpaddedTestVectors() {
+ /**
+ * @return void
+ */
+ public function testKnownBase32DecodeUnpaddedTestVectors()
+ {
// See testKnownBase32DecodeTestVectors() for the rationale behind testing the private base32Decode() method.
// This test ensures that strings without the padding-char ('=') are also decoded correctly.
// https://tools.ietf.org/html/rfc4648#page-4:
// "In some circumstances, the use of padding ("=") in base-encoded data is not required or used."
$tfa = new TwoFactorAuth('Test');
- $method = new ReflectionMethod('RobThree\Auth\TwoFactorAuth', 'base32Decode');
+ $method = new \ReflectionMethod(TwoFactorAuth::class, 'base32Decode');
$method->setAccessible(true);
// Test vectors from: https://tools.ietf.org/html/rfc4648#page-12
@@ -259,8 +196,11 @@
$this->assertEquals('foobar', $method->invoke($tfa, 'MZXW6YTBOI'));
}
-
- public function testKnownTestVectors_sha1() {
+ /**
+ * @return void
+ */
+ public function testKnownTestVectors_sha1()
+ {
//Known test vectors for SHA1: https://tools.ietf.org/html/rfc6238#page-15
$secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ'; //== base32encode('12345678901234567890')
$tfa = new TwoFactorAuth('Test', 8, 30, 'sha1');
@@ -272,7 +212,11 @@
$this->assertEquals('65353130', $tfa->getCode($secret, 20000000000));
}
- public function testKnownTestVectors_sha256() {
+ /**
+ * @return void
+ */
+ public function testKnownTestVectors_sha256()
+ {
//Known test vectors for SHA256: https://tools.ietf.org/html/rfc6238#page-15
$secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZA'; //== base32encode('12345678901234567890123456789012')
$tfa = new TwoFactorAuth('Test', 8, 30, 'sha256');
@@ -284,7 +228,11 @@
$this->assertEquals('77737706', $tfa->getCode($secret, 20000000000));
}
- public function testKnownTestVectors_sha512() {
+ /**
+ * @return void
+ */
+ public function testKnownTestVectors_sha512()
+ {
//Known test vectors for SHA512: https://tools.ietf.org/html/rfc6238#page-15
$secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNA'; //== base32encode('1234567890123456789012345678901234567890123456789012345678901234')
$tfa = new TwoFactorAuth('Test', 8, 30, 'sha512');
@@ -295,115 +243,4 @@
$this->assertEquals('38618901', $tfa->getCode($secret, 2000000000));
$this->assertEquals('47863826', $tfa->getCode($secret, 20000000000));
}
-
- /**
- * @requires function random_bytes
- */
- public function testCSRNGProvidersReturnExpectedNumberOfBytes() {
- $rng = new \RobThree\Auth\Providers\Rng\CSRNGProvider();
- foreach ($this->getRngTestLengths() as $l)
- $this->assertEquals($l, strlen($rng->getRandomBytes($l)));
- $this->assertEquals(true, $rng->isCryptographicallySecure());
- }
-
- /**
- * @requires function hash_algos
- * @requires function hash
- */
- public function testHashRNGProvidersReturnExpectedNumberOfBytes() {
- $rng = new \RobThree\Auth\Providers\Rng\HashRNGProvider();
- foreach ($this->getRngTestLengths() as $l)
- $this->assertEquals($l, strlen($rng->getRandomBytes($l)));
- $this->assertEquals(false, $rng->isCryptographicallySecure());
- }
-
- /**
- * @requires function mcrypt_create_iv
- */
- public function testMCryptRNGProvidersReturnExpectedNumberOfBytes() {
- if (function_exists('mcrypt_create_iv')) {
- $rng = new \RobThree\Auth\Providers\Rng\MCryptRNGProvider();
- foreach ($this->getRngTestLengths() as $l)
- $this->assertEquals($l, strlen($rng->getRandomBytes($l)));
- $this->assertEquals(true, $rng->isCryptographicallySecure());
- }
- }
-
- /**
- * @requires function openssl_random_pseudo_bytes
- */
- public function testStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() {
- $rng = new \RobThree\Auth\Providers\Rng\OpenSSLRNGProvider(true);
- foreach ($this->getRngTestLengths() as $l)
- $this->assertEquals($l, strlen($rng->getRandomBytes($l)));
- $this->assertEquals(true, $rng->isCryptographicallySecure());
- }
-
- /**
- * @requires function openssl_random_pseudo_bytes
- */
- public function testNonStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() {
- $rng = new \RobThree\Auth\Providers\Rng\OpenSSLRNGProvider(false);
- foreach ($this->getRngTestLengths() as $l)
- $this->assertEquals($l, strlen($rng->getRandomBytes($l)));
- $this->assertEquals(false, $rng->isCryptographicallySecure());
- }
-
-
- private function getRngTestLengths() {
- return array(1, 16, 32, 256);
- }
-
- private function DecodeDataUri($datauri) {
- if (preg_match('/data:(?P<mimetype>[\w\.\-\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
- return array(
- 'mimetype' => $m['mimetype'],
- 'encoding' => $m['encoding'],
- 'data' => base64_decode($m['data'])
- );
- }
- return null;
- }
}
-
-class TestRNGProvider implements IRNGProvider {
- private $isSecure;
-
- function __construct($isSecure = false) {
- $this->isSecure = $isSecure;
- }
-
- public function getRandomBytes($bytecount) {
- $result = '';
- for ($i=0; $i<$bytecount; $i++)
- $result.=chr($i);
- return $result;
-
- }
-
- public function isCryptographicallySecure() {
- return $this->isSecure;
- }
-}
-
-class TestQrProvider implements IQRCodeProvider {
- public function getQRCodeImage($qrtext, $size) {
- return $qrtext . '@' . $size;
- }
-
- public function getMimeType() {
- return 'test/test';
- }
-}
-
-class TestTimeProvider implements ITimeProvider {
- private $time;
-
- function __construct($time) {
- $this->time = $time;
- }
-
- public function getTime() {
- return $this->time;
- }
-}
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/.gitignore b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/.gitignore
new file mode 100644
index 0000000..c49a5d8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/CHANGELOG.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/CHANGELOG.md
new file mode 100644
index 0000000..7932e26
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/CHANGELOG.md
@@ -0,0 +1,5 @@
+CHANGELOG
+=========
+
+The changelog is maintained for all Symfony contracts at the following URL:
+https://github.com/symfony/contracts/blob/main/CHANGELOG.md
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/LICENSE
new file mode 100644
index 0000000..ad85e17
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2020-2021 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/README.md
new file mode 100644
index 0000000..4957933
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/README.md
@@ -0,0 +1,26 @@
+Symfony Deprecation Contracts
+=============================
+
+A generic function and convention to trigger deprecation notices.
+
+This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices.
+
+By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component,
+the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments.
+
+The function requires at least 3 arguments:
+ - the name of the Composer package that is triggering the deprecation
+ - the version of the package that introduced the deprecation
+ - the message of the deprecation
+ - more arguments can be provided: they will be inserted in the message using `printf()` formatting
+
+Example:
+```php
+trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin');
+```
+
+This will generate the following message:
+`Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.`
+
+While not necessarily recommended, the deprecation notices can be completely ignored by declaring an empty
+`function trigger_deprecation() {}` in your application.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/composer.json
new file mode 100644
index 0000000..3884889
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/composer.json
@@ -0,0 +1,35 @@
+{
+ "name": "symfony/deprecation-contracts",
+ "type": "library",
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.1"
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/function.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/function.php
new file mode 100644
index 0000000..d437150
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/deprecation-contracts/function.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+if (!function_exists('trigger_deprecation')) {
+ /**
+ * Triggers a silenced deprecation notice.
+ *
+ * @param string $package The name of the Composer package that is triggering the deprecation
+ * @param string $version The version of the package that introduced the deprecation
+ * @param string $message The message of the deprecation
+ * @param mixed ...$args Values to insert in the message using printf() formatting
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+ function trigger_deprecation(string $package, string $version, string $message, ...$args): void
+ {
+ @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/LICENSE
new file mode 100644
index 0000000..4cd8bdd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015-2019 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Mbstring.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Mbstring.php
new file mode 100644
index 0000000..b599095
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Mbstring.php
@@ -0,0 +1,870 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Mbstring;
+
+/**
+ * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
+ *
+ * Implemented:
+ * - mb_chr - Returns a specific character from its Unicode code point
+ * - mb_convert_encoding - Convert character encoding
+ * - mb_convert_variables - Convert character code in variable(s)
+ * - mb_decode_mimeheader - Decode string in MIME header field
+ * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
+ * - mb_decode_numericentity - Decode HTML numeric string reference to character
+ * - mb_encode_numericentity - Encode character to HTML numeric string reference
+ * - mb_convert_case - Perform case folding on a string
+ * - mb_detect_encoding - Detect character encoding
+ * - mb_get_info - Get internal settings of mbstring
+ * - mb_http_input - Detect HTTP input character encoding
+ * - mb_http_output - Set/Get HTTP output character encoding
+ * - mb_internal_encoding - Set/Get internal character encoding
+ * - mb_list_encodings - Returns an array of all supported encodings
+ * - mb_ord - Returns the Unicode code point of a character
+ * - mb_output_handler - Callback function converts character encoding in output buffer
+ * - mb_scrub - Replaces ill-formed byte sequences with substitute characters
+ * - mb_strlen - Get string length
+ * - mb_strpos - Find position of first occurrence of string in a string
+ * - mb_strrpos - Find position of last occurrence of a string in a string
+ * - mb_str_split - Convert a string to an array
+ * - mb_strtolower - Make a string lowercase
+ * - mb_strtoupper - Make a string uppercase
+ * - mb_substitute_character - Set/Get substitution character
+ * - mb_substr - Get part of string
+ * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive
+ * - mb_stristr - Finds first occurrence of a string within another, case insensitive
+ * - mb_strrchr - Finds the last occurrence of a character in a string within another
+ * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive
+ * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive
+ * - mb_strstr - Finds first occurrence of a string within another
+ * - mb_strwidth - Return width of string
+ * - mb_substr_count - Count the number of substring occurrences
+ *
+ * Not implemented:
+ * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
+ * - mb_ereg_* - Regular expression with multibyte support
+ * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable
+ * - mb_preferred_mime_name - Get MIME charset string
+ * - mb_regex_encoding - Returns current encoding for multibyte regex as string
+ * - mb_regex_set_options - Set/Get the default options for mbregex functions
+ * - mb_send_mail - Send encoded mail
+ * - mb_split - Split multibyte string using regular expression
+ * - mb_strcut - Get part of string
+ * - mb_strimwidth - Get truncated string with specified width
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @internal
+ */
+final class Mbstring
+{
+ public const MB_CASE_FOLD = \PHP_INT_MAX;
+
+ private const CASE_FOLD = [
+ ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"],
+ ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'],
+ ];
+
+ private static $encodingList = ['ASCII', 'UTF-8'];
+ private static $language = 'neutral';
+ private static $internalEncoding = 'UTF-8';
+
+ public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
+ {
+ if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
+ $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
+ } else {
+ $fromEncoding = self::getEncoding($fromEncoding);
+ }
+
+ $toEncoding = self::getEncoding($toEncoding);
+
+ if ('BASE64' === $fromEncoding) {
+ $s = base64_decode($s);
+ $fromEncoding = $toEncoding;
+ }
+
+ if ('BASE64' === $toEncoding) {
+ return base64_encode($s);
+ }
+
+ if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
+ if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
+ $fromEncoding = 'Windows-1252';
+ }
+ if ('UTF-8' !== $fromEncoding) {
+ $s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s);
+ }
+
+ return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
+ }
+
+ if ('HTML-ENTITIES' === $fromEncoding) {
+ $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
+ $fromEncoding = 'UTF-8';
+ }
+
+ return \iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
+ }
+
+ public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
+ {
+ $ok = true;
+ array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
+ if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
+ $ok = false;
+ }
+ });
+
+ return $ok ? $fromEncoding : false;
+ }
+
+ public static function mb_decode_mimeheader($s)
+ {
+ return \iconv_mime_decode($s, 2, self::$internalEncoding);
+ }
+
+ public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
+ {
+ trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
+ }
+
+ public static function mb_decode_numericentity($s, $convmap, $encoding = null)
+ {
+ if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
+ trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
+
+ return null;
+ }
+
+ if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
+ return false;
+ }
+
+ if (null !== $encoding && !is_scalar($encoding)) {
+ trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
+
+ return ''; // Instead of null (cf. mb_encode_numericentity).
+ }
+
+ $s = (string) $s;
+ if ('' === $s) {
+ return '';
+ }
+
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' === $encoding) {
+ $encoding = null;
+ if (!preg_match('//u', $s)) {
+ $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
+ }
+ } else {
+ $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
+ }
+
+ $cnt = floor(\count($convmap) / 4) * 4;
+
+ for ($i = 0; $i < $cnt; $i += 4) {
+ // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
+ $convmap[$i] += $convmap[$i + 2];
+ $convmap[$i + 1] += $convmap[$i + 2];
+ }
+
+ $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
+ $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
+ for ($i = 0; $i < $cnt; $i += 4) {
+ if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
+ return self::mb_chr($c - $convmap[$i + 2]);
+ }
+ }
+
+ return $m[0];
+ }, $s);
+
+ if (null === $encoding) {
+ return $s;
+ }
+
+ return \iconv('UTF-8', $encoding.'//IGNORE', $s);
+ }
+
+ public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
+ {
+ if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
+ trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
+
+ return null;
+ }
+
+ if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
+ return false;
+ }
+
+ if (null !== $encoding && !is_scalar($encoding)) {
+ trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
+
+ return null; // Instead of '' (cf. mb_decode_numericentity).
+ }
+
+ if (null !== $is_hex && !is_scalar($is_hex)) {
+ trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING);
+
+ return null;
+ }
+
+ $s = (string) $s;
+ if ('' === $s) {
+ return '';
+ }
+
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' === $encoding) {
+ $encoding = null;
+ if (!preg_match('//u', $s)) {
+ $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
+ }
+ } else {
+ $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
+ }
+
+ static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
+
+ $cnt = floor(\count($convmap) / 4) * 4;
+ $i = 0;
+ $len = \strlen($s);
+ $result = '';
+
+ while ($i < $len) {
+ $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
+ $uchr = substr($s, $i, $ulen);
+ $i += $ulen;
+ $c = self::mb_ord($uchr);
+
+ for ($j = 0; $j < $cnt; $j += 4) {
+ if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
+ $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
+ $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
+ continue 2;
+ }
+ }
+ $result .= $uchr;
+ }
+
+ if (null === $encoding) {
+ return $result;
+ }
+
+ return \iconv('UTF-8', $encoding.'//IGNORE', $result);
+ }
+
+ public static function mb_convert_case($s, $mode, $encoding = null)
+ {
+ $s = (string) $s;
+ if ('' === $s) {
+ return '';
+ }
+
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' === $encoding) {
+ $encoding = null;
+ if (!preg_match('//u', $s)) {
+ $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
+ }
+ } else {
+ $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
+ }
+
+ if (\MB_CASE_TITLE == $mode) {
+ static $titleRegexp = null;
+ if (null === $titleRegexp) {
+ $titleRegexp = self::getData('titleCaseRegexp');
+ }
+ $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
+ } else {
+ if (\MB_CASE_UPPER == $mode) {
+ static $upper = null;
+ if (null === $upper) {
+ $upper = self::getData('upperCase');
+ }
+ $map = $upper;
+ } else {
+ if (self::MB_CASE_FOLD === $mode) {
+ $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
+ }
+
+ static $lower = null;
+ if (null === $lower) {
+ $lower = self::getData('lowerCase');
+ }
+ $map = $lower;
+ }
+
+ static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
+
+ $i = 0;
+ $len = \strlen($s);
+
+ while ($i < $len) {
+ $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
+ $uchr = substr($s, $i, $ulen);
+ $i += $ulen;
+
+ if (isset($map[$uchr])) {
+ $uchr = $map[$uchr];
+ $nlen = \strlen($uchr);
+
+ if ($nlen == $ulen) {
+ $nlen = $i;
+ do {
+ $s[--$nlen] = $uchr[--$ulen];
+ } while ($ulen);
+ } else {
+ $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
+ $len += $nlen - $ulen;
+ $i += $nlen - $ulen;
+ }
+ }
+ }
+ }
+
+ if (null === $encoding) {
+ return $s;
+ }
+
+ return \iconv('UTF-8', $encoding.'//IGNORE', $s);
+ }
+
+ public static function mb_internal_encoding($encoding = null)
+ {
+ if (null === $encoding) {
+ return self::$internalEncoding;
+ }
+
+ $normalizedEncoding = self::getEncoding($encoding);
+
+ if ('UTF-8' === $normalizedEncoding || false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
+ self::$internalEncoding = $normalizedEncoding;
+
+ return true;
+ }
+
+ if (80000 > \PHP_VERSION_ID) {
+ return false;
+ }
+
+ throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
+ }
+
+ public static function mb_language($lang = null)
+ {
+ if (null === $lang) {
+ return self::$language;
+ }
+
+ switch ($normalizedLang = strtolower($lang)) {
+ case 'uni':
+ case 'neutral':
+ self::$language = $normalizedLang;
+
+ return true;
+ }
+
+ if (80000 > \PHP_VERSION_ID) {
+ return false;
+ }
+
+ throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
+ }
+
+ public static function mb_list_encodings()
+ {
+ return ['UTF-8'];
+ }
+
+ public static function mb_encoding_aliases($encoding)
+ {
+ switch (strtoupper($encoding)) {
+ case 'UTF8':
+ case 'UTF-8':
+ return ['utf8'];
+ }
+
+ return false;
+ }
+
+ public static function mb_check_encoding($var = null, $encoding = null)
+ {
+ if (null === $encoding) {
+ if (null === $var) {
+ return false;
+ }
+ $encoding = self::$internalEncoding;
+ }
+
+ return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var);
+ }
+
+ public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
+ {
+ if (null === $encodingList) {
+ $encodingList = self::$encodingList;
+ } else {
+ if (!\is_array($encodingList)) {
+ $encodingList = array_map('trim', explode(',', $encodingList));
+ }
+ $encodingList = array_map('strtoupper', $encodingList);
+ }
+
+ foreach ($encodingList as $enc) {
+ switch ($enc) {
+ case 'ASCII':
+ if (!preg_match('/[\x80-\xFF]/', $str)) {
+ return $enc;
+ }
+ break;
+
+ case 'UTF8':
+ case 'UTF-8':
+ if (preg_match('//u', $str)) {
+ return 'UTF-8';
+ }
+ break;
+
+ default:
+ if (0 === strncmp($enc, 'ISO-8859-', 9)) {
+ return $enc;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static function mb_detect_order($encodingList = null)
+ {
+ if (null === $encodingList) {
+ return self::$encodingList;
+ }
+
+ if (!\is_array($encodingList)) {
+ $encodingList = array_map('trim', explode(',', $encodingList));
+ }
+ $encodingList = array_map('strtoupper', $encodingList);
+
+ foreach ($encodingList as $enc) {
+ switch ($enc) {
+ default:
+ if (strncmp($enc, 'ISO-8859-', 9)) {
+ return false;
+ }
+ // no break
+ case 'ASCII':
+ case 'UTF8':
+ case 'UTF-8':
+ }
+ }
+
+ self::$encodingList = $encodingList;
+
+ return true;
+ }
+
+ public static function mb_strlen($s, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
+ return \strlen($s);
+ }
+
+ return @\iconv_strlen($s, $encoding);
+ }
+
+ public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
+ return strpos($haystack, $needle, $offset);
+ }
+
+ $needle = (string) $needle;
+ if ('' === $needle) {
+ if (80000 > \PHP_VERSION_ID) {
+ trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING);
+
+ return false;
+ }
+
+ return 0;
+ }
+
+ return \iconv_strpos($haystack, $needle, $offset, $encoding);
+ }
+
+ public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
+ return strrpos($haystack, $needle, $offset);
+ }
+
+ if ($offset != (int) $offset) {
+ $offset = 0;
+ } elseif ($offset = (int) $offset) {
+ if ($offset < 0) {
+ if (0 > $offset += self::mb_strlen($needle)) {
+ $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
+ }
+ $offset = 0;
+ } else {
+ $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
+ }
+ }
+
+ $pos = '' !== $needle || 80000 > \PHP_VERSION_ID
+ ? \iconv_strrpos($haystack, $needle, $encoding)
+ : self::mb_strlen($haystack, $encoding);
+
+ return false !== $pos ? $offset + $pos : false;
+ }
+
+ public static function mb_str_split($string, $split_length = 1, $encoding = null)
+ {
+ if (null !== $string && !is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
+ trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING);
+
+ return null;
+ }
+
+ if (1 > $split_length = (int) $split_length) {
+ if (80000 > \PHP_VERSION_ID) {
+ trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
+ return false;
+ }
+
+ throw new \ValueError('Argument #2 ($length) must be greater than 0');
+ }
+
+ if (null === $encoding) {
+ $encoding = mb_internal_encoding();
+ }
+
+ if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
+ $rx = '/(';
+ while (65535 < $split_length) {
+ $rx .= '.{65535}';
+ $split_length -= 65535;
+ }
+ $rx .= '.{'.$split_length.'})/us';
+
+ return preg_split($rx, $string, null, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
+ }
+
+ $result = [];
+ $length = mb_strlen($string, $encoding);
+
+ for ($i = 0; $i < $length; $i += $split_length) {
+ $result[] = mb_substr($string, $i, $split_length, $encoding);
+ }
+
+ return $result;
+ }
+
+ public static function mb_strtolower($s, $encoding = null)
+ {
+ return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
+ }
+
+ public static function mb_strtoupper($s, $encoding = null)
+ {
+ return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
+ }
+
+ public static function mb_substitute_character($c = null)
+ {
+ if (null === $c) {
+ return 'none';
+ }
+ if (0 === strcasecmp($c, 'none')) {
+ return true;
+ }
+ if (80000 > \PHP_VERSION_ID) {
+ return false;
+ }
+
+ throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
+ }
+
+ public static function mb_substr($s, $start, $length = null, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
+ return (string) substr($s, $start, null === $length ? 2147483647 : $length);
+ }
+
+ if ($start < 0) {
+ $start = \iconv_strlen($s, $encoding) + $start;
+ if ($start < 0) {
+ $start = 0;
+ }
+ }
+
+ if (null === $length) {
+ $length = 2147483647;
+ } elseif ($length < 0) {
+ $length = \iconv_strlen($s, $encoding) + $length - $start;
+ if ($length < 0) {
+ return '';
+ }
+ }
+
+ return (string) \iconv_substr($s, $start, $length, $encoding);
+ }
+
+ public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
+ {
+ $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
+ $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
+
+ return self::mb_strpos($haystack, $needle, $offset, $encoding);
+ }
+
+ public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
+ {
+ $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
+
+ return self::getSubpart($pos, $part, $haystack, $encoding);
+ }
+
+ public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
+ $pos = strrpos($haystack, $needle);
+ } else {
+ $needle = self::mb_substr($needle, 0, 1, $encoding);
+ $pos = \iconv_strrpos($haystack, $needle, $encoding);
+ }
+
+ return self::getSubpart($pos, $part, $haystack, $encoding);
+ }
+
+ public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
+ {
+ $needle = self::mb_substr($needle, 0, 1, $encoding);
+ $pos = self::mb_strripos($haystack, $needle, $encoding);
+
+ return self::getSubpart($pos, $part, $haystack, $encoding);
+ }
+
+ public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
+ {
+ $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
+ $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
+
+ return self::mb_strrpos($haystack, $needle, $offset, $encoding);
+ }
+
+ public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
+ {
+ $pos = strpos($haystack, $needle);
+ if (false === $pos) {
+ return false;
+ }
+ if ($part) {
+ return substr($haystack, 0, $pos);
+ }
+
+ return substr($haystack, $pos);
+ }
+
+ public static function mb_get_info($type = 'all')
+ {
+ $info = [
+ 'internal_encoding' => self::$internalEncoding,
+ 'http_output' => 'pass',
+ 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
+ 'func_overload' => 0,
+ 'func_overload_list' => 'no overload',
+ 'mail_charset' => 'UTF-8',
+ 'mail_header_encoding' => 'BASE64',
+ 'mail_body_encoding' => 'BASE64',
+ 'illegal_chars' => 0,
+ 'encoding_translation' => 'Off',
+ 'language' => self::$language,
+ 'detect_order' => self::$encodingList,
+ 'substitute_character' => 'none',
+ 'strict_detection' => 'Off',
+ ];
+
+ if ('all' === $type) {
+ return $info;
+ }
+ if (isset($info[$type])) {
+ return $info[$type];
+ }
+
+ return false;
+ }
+
+ public static function mb_http_input($type = '')
+ {
+ return false;
+ }
+
+ public static function mb_http_output($encoding = null)
+ {
+ return null !== $encoding ? 'pass' === $encoding : 'pass';
+ }
+
+ public static function mb_strwidth($s, $encoding = null)
+ {
+ $encoding = self::getEncoding($encoding);
+
+ if ('UTF-8' !== $encoding) {
+ $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
+ }
+
+ $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);
+
+ return ($wide << 1) + \iconv_strlen($s, 'UTF-8');
+ }
+
+ public static function mb_substr_count($haystack, $needle, $encoding = null)
+ {
+ return substr_count($haystack, $needle);
+ }
+
+ public static function mb_output_handler($contents, $status)
+ {
+ return $contents;
+ }
+
+ public static function mb_chr($code, $encoding = null)
+ {
+ if (0x80 > $code %= 0x200000) {
+ $s = \chr($code);
+ } elseif (0x800 > $code) {
+ $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
+ } elseif (0x10000 > $code) {
+ $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
+ } else {
+ $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
+ }
+
+ if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
+ $s = mb_convert_encoding($s, $encoding, 'UTF-8');
+ }
+
+ return $s;
+ }
+
+ public static function mb_ord($s, $encoding = null)
+ {
+ if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
+ $s = mb_convert_encoding($s, 'UTF-8', $encoding);
+ }
+
+ if (1 === \strlen($s)) {
+ return \ord($s);
+ }
+
+ $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
+ if (0xF0 <= $code) {
+ return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
+ }
+ if (0xE0 <= $code) {
+ return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
+ }
+ if (0xC0 <= $code) {
+ return (($code - 0xC0) << 6) + $s[2] - 0x80;
+ }
+
+ return $code;
+ }
+
+ private static function getSubpart($pos, $part, $haystack, $encoding)
+ {
+ if (false === $pos) {
+ return false;
+ }
+ if ($part) {
+ return self::mb_substr($haystack, 0, $pos, $encoding);
+ }
+
+ return self::mb_substr($haystack, $pos, null, $encoding);
+ }
+
+ private static function html_encoding_callback(array $m)
+ {
+ $i = 1;
+ $entities = '';
+ $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
+
+ while (isset($m[$i])) {
+ if (0x80 > $m[$i]) {
+ $entities .= \chr($m[$i++]);
+ continue;
+ }
+ if (0xF0 <= $m[$i]) {
+ $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
+ } elseif (0xE0 <= $m[$i]) {
+ $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
+ } else {
+ $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
+ }
+
+ $entities .= '&#'.$c.';';
+ }
+
+ return $entities;
+ }
+
+ private static function title_case(array $s)
+ {
+ return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
+ }
+
+ private static function getData($file)
+ {
+ if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
+ return require $file;
+ }
+
+ return false;
+ }
+
+ private static function getEncoding($encoding)
+ {
+ if (null === $encoding) {
+ return self::$internalEncoding;
+ }
+
+ if ('UTF-8' === $encoding) {
+ return 'UTF-8';
+ }
+
+ $encoding = strtoupper($encoding);
+
+ if ('8BIT' === $encoding || 'BINARY' === $encoding) {
+ return 'CP850';
+ }
+
+ if ('UTF8' === $encoding) {
+ return 'UTF-8';
+ }
+
+ return $encoding;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/README.md
new file mode 100644
index 0000000..4efb599
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/README.md
@@ -0,0 +1,13 @@
+Symfony Polyfill / Mbstring
+===========================
+
+This component provides a partial, native PHP implementation for the
+[Mbstring](https://php.net/mbstring) extension.
+
+More information can be found in the
+[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
+
+License
+=======
+
+This library is released under the [MIT license](LICENSE).
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
new file mode 100644
index 0000000..fac60b0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
@@ -0,0 +1,1397 @@
+<?php
+
+return array (
+ 'A' => 'a',
+ 'B' => 'b',
+ 'C' => 'c',
+ 'D' => 'd',
+ 'E' => 'e',
+ 'F' => 'f',
+ 'G' => 'g',
+ 'H' => 'h',
+ 'I' => 'i',
+ 'J' => 'j',
+ 'K' => 'k',
+ 'L' => 'l',
+ 'M' => 'm',
+ 'N' => 'n',
+ 'O' => 'o',
+ 'P' => 'p',
+ 'Q' => 'q',
+ 'R' => 'r',
+ 'S' => 's',
+ 'T' => 't',
+ 'U' => 'u',
+ 'V' => 'v',
+ 'W' => 'w',
+ 'X' => 'x',
+ 'Y' => 'y',
+ 'Z' => 'z',
+ 'À' => 'à',
+ 'Á' => 'á',
+ 'Â' => 'â',
+ 'Ã' => 'ã',
+ 'Ä' => 'ä',
+ 'Å' => 'å',
+ 'Æ' => 'æ',
+ 'Ç' => 'ç',
+ 'È' => 'è',
+ 'É' => 'é',
+ 'Ê' => 'ê',
+ 'Ë' => 'ë',
+ 'Ì' => 'ì',
+ 'Í' => 'í',
+ 'Î' => 'î',
+ 'Ï' => 'ï',
+ 'Ð' => 'ð',
+ 'Ñ' => 'ñ',
+ 'Ò' => 'ò',
+ 'Ó' => 'ó',
+ 'Ô' => 'ô',
+ 'Õ' => 'õ',
+ 'Ö' => 'ö',
+ 'Ø' => 'ø',
+ 'Ù' => 'ù',
+ 'Ú' => 'ú',
+ 'Û' => 'û',
+ 'Ü' => 'ü',
+ 'Ý' => 'ý',
+ 'Þ' => 'þ',
+ 'Ā' => 'ā',
+ 'Ă' => 'ă',
+ 'Ą' => 'ą',
+ 'Ć' => 'ć',
+ 'Ĉ' => 'ĉ',
+ 'Ċ' => 'ċ',
+ 'Č' => 'č',
+ 'Ď' => 'ď',
+ 'Đ' => 'đ',
+ 'Ē' => 'ē',
+ 'Ĕ' => 'ĕ',
+ 'Ė' => 'ė',
+ 'Ę' => 'ę',
+ 'Ě' => 'ě',
+ 'Ĝ' => 'ĝ',
+ 'Ğ' => 'ğ',
+ 'Ġ' => 'ġ',
+ 'Ģ' => 'ģ',
+ 'Ĥ' => 'ĥ',
+ 'Ħ' => 'ħ',
+ 'Ĩ' => 'ĩ',
+ 'Ī' => 'ī',
+ 'Ĭ' => 'ĭ',
+ 'Į' => 'į',
+ 'İ' => 'i̇',
+ 'IJ' => 'ij',
+ 'Ĵ' => 'ĵ',
+ 'Ķ' => 'ķ',
+ 'Ĺ' => 'ĺ',
+ 'Ļ' => 'ļ',
+ 'Ľ' => 'ľ',
+ 'Ŀ' => 'ŀ',
+ 'Ł' => 'ł',
+ 'Ń' => 'ń',
+ 'Ņ' => 'ņ',
+ 'Ň' => 'ň',
+ 'Ŋ' => 'ŋ',
+ 'Ō' => 'ō',
+ 'Ŏ' => 'ŏ',
+ 'Ő' => 'ő',
+ 'Œ' => 'œ',
+ 'Ŕ' => 'ŕ',
+ 'Ŗ' => 'ŗ',
+ 'Ř' => 'ř',
+ 'Ś' => 'ś',
+ 'Ŝ' => 'ŝ',
+ 'Ş' => 'ş',
+ 'Š' => 'š',
+ 'Ţ' => 'ţ',
+ 'Ť' => 'ť',
+ 'Ŧ' => 'ŧ',
+ 'Ũ' => 'ũ',
+ 'Ū' => 'ū',
+ 'Ŭ' => 'ŭ',
+ 'Ů' => 'ů',
+ 'Ű' => 'ű',
+ 'Ų' => 'ų',
+ 'Ŵ' => 'ŵ',
+ 'Ŷ' => 'ŷ',
+ 'Ÿ' => 'ÿ',
+ 'Ź' => 'ź',
+ 'Ż' => 'ż',
+ 'Ž' => 'ž',
+ 'Ɓ' => 'ɓ',
+ 'Ƃ' => 'ƃ',
+ 'Ƅ' => 'ƅ',
+ 'Ɔ' => 'ɔ',
+ 'Ƈ' => 'ƈ',
+ 'Ɖ' => 'ɖ',
+ 'Ɗ' => 'ɗ',
+ 'Ƌ' => 'ƌ',
+ 'Ǝ' => 'ǝ',
+ 'Ə' => 'ə',
+ 'Ɛ' => 'ɛ',
+ 'Ƒ' => 'ƒ',
+ 'Ɠ' => 'ɠ',
+ 'Ɣ' => 'ɣ',
+ 'Ɩ' => 'ɩ',
+ 'Ɨ' => 'ɨ',
+ 'Ƙ' => 'ƙ',
+ 'Ɯ' => 'ɯ',
+ 'Ɲ' => 'ɲ',
+ 'Ɵ' => 'ɵ',
+ 'Ơ' => 'ơ',
+ 'Ƣ' => 'ƣ',
+ 'Ƥ' => 'ƥ',
+ 'Ʀ' => 'ʀ',
+ 'Ƨ' => 'ƨ',
+ 'Ʃ' => 'ʃ',
+ 'Ƭ' => 'ƭ',
+ 'Ʈ' => 'ʈ',
+ 'Ư' => 'ư',
+ 'Ʊ' => 'ʊ',
+ 'Ʋ' => 'ʋ',
+ 'Ƴ' => 'ƴ',
+ 'Ƶ' => 'ƶ',
+ 'Ʒ' => 'ʒ',
+ 'Ƹ' => 'ƹ',
+ 'Ƽ' => 'ƽ',
+ 'DŽ' => 'dž',
+ 'Dž' => 'dž',
+ 'LJ' => 'lj',
+ 'Lj' => 'lj',
+ 'NJ' => 'nj',
+ 'Nj' => 'nj',
+ 'Ǎ' => 'ǎ',
+ 'Ǐ' => 'ǐ',
+ 'Ǒ' => 'ǒ',
+ 'Ǔ' => 'ǔ',
+ 'Ǖ' => 'ǖ',
+ 'Ǘ' => 'ǘ',
+ 'Ǚ' => 'ǚ',
+ 'Ǜ' => 'ǜ',
+ 'Ǟ' => 'ǟ',
+ 'Ǡ' => 'ǡ',
+ 'Ǣ' => 'ǣ',
+ 'Ǥ' => 'ǥ',
+ 'Ǧ' => 'ǧ',
+ 'Ǩ' => 'ǩ',
+ 'Ǫ' => 'ǫ',
+ 'Ǭ' => 'ǭ',
+ 'Ǯ' => 'ǯ',
+ 'DZ' => 'dz',
+ 'Dz' => 'dz',
+ 'Ǵ' => 'ǵ',
+ 'Ƕ' => 'ƕ',
+ 'Ƿ' => 'ƿ',
+ 'Ǹ' => 'ǹ',
+ 'Ǻ' => 'ǻ',
+ 'Ǽ' => 'ǽ',
+ 'Ǿ' => 'ǿ',
+ 'Ȁ' => 'ȁ',
+ 'Ȃ' => 'ȃ',
+ 'Ȅ' => 'ȅ',
+ 'Ȇ' => 'ȇ',
+ 'Ȉ' => 'ȉ',
+ 'Ȋ' => 'ȋ',
+ 'Ȍ' => 'ȍ',
+ 'Ȏ' => 'ȏ',
+ 'Ȑ' => 'ȑ',
+ 'Ȓ' => 'ȓ',
+ 'Ȕ' => 'ȕ',
+ 'Ȗ' => 'ȗ',
+ 'Ș' => 'ș',
+ 'Ț' => 'ț',
+ 'Ȝ' => 'ȝ',
+ 'Ȟ' => 'ȟ',
+ 'Ƞ' => 'ƞ',
+ 'Ȣ' => 'ȣ',
+ 'Ȥ' => 'ȥ',
+ 'Ȧ' => 'ȧ',
+ 'Ȩ' => 'ȩ',
+ 'Ȫ' => 'ȫ',
+ 'Ȭ' => 'ȭ',
+ 'Ȯ' => 'ȯ',
+ 'Ȱ' => 'ȱ',
+ 'Ȳ' => 'ȳ',
+ 'Ⱥ' => 'ⱥ',
+ 'Ȼ' => 'ȼ',
+ 'Ƚ' => 'ƚ',
+ 'Ⱦ' => 'ⱦ',
+ 'Ɂ' => 'ɂ',
+ 'Ƀ' => 'ƀ',
+ 'Ʉ' => 'ʉ',
+ 'Ʌ' => 'ʌ',
+ 'Ɇ' => 'ɇ',
+ 'Ɉ' => 'ɉ',
+ 'Ɋ' => 'ɋ',
+ 'Ɍ' => 'ɍ',
+ 'Ɏ' => 'ɏ',
+ 'Ͱ' => 'ͱ',
+ 'Ͳ' => 'ͳ',
+ 'Ͷ' => 'ͷ',
+ 'Ϳ' => 'ϳ',
+ 'Ά' => 'ά',
+ 'Έ' => 'έ',
+ 'Ή' => 'ή',
+ 'Ί' => 'ί',
+ 'Ό' => 'ό',
+ 'Ύ' => 'ύ',
+ 'Ώ' => 'ώ',
+ 'Α' => 'α',
+ 'Β' => 'β',
+ 'Γ' => 'γ',
+ 'Δ' => 'δ',
+ 'Ε' => 'ε',
+ 'Ζ' => 'ζ',
+ 'Η' => 'η',
+ 'Θ' => 'θ',
+ 'Ι' => 'ι',
+ 'Κ' => 'κ',
+ 'Λ' => 'λ',
+ 'Μ' => 'μ',
+ 'Ν' => 'ν',
+ 'Ξ' => 'ξ',
+ 'Ο' => 'ο',
+ 'Π' => 'π',
+ 'Ρ' => 'ρ',
+ 'Σ' => 'σ',
+ 'Τ' => 'τ',
+ 'Υ' => 'υ',
+ 'Φ' => 'φ',
+ 'Χ' => 'χ',
+ 'Ψ' => 'ψ',
+ 'Ω' => 'ω',
+ 'Ϊ' => 'ϊ',
+ 'Ϋ' => 'ϋ',
+ 'Ϗ' => 'ϗ',
+ 'Ϙ' => 'ϙ',
+ 'Ϛ' => 'ϛ',
+ 'Ϝ' => 'ϝ',
+ 'Ϟ' => 'ϟ',
+ 'Ϡ' => 'ϡ',
+ 'Ϣ' => 'ϣ',
+ 'Ϥ' => 'ϥ',
+ 'Ϧ' => 'ϧ',
+ 'Ϩ' => 'ϩ',
+ 'Ϫ' => 'ϫ',
+ 'Ϭ' => 'ϭ',
+ 'Ϯ' => 'ϯ',
+ 'ϴ' => 'θ',
+ 'Ϸ' => 'ϸ',
+ 'Ϲ' => 'ϲ',
+ 'Ϻ' => 'ϻ',
+ 'Ͻ' => 'ͻ',
+ 'Ͼ' => 'ͼ',
+ 'Ͽ' => 'ͽ',
+ 'Ѐ' => 'ѐ',
+ 'Ё' => 'ё',
+ 'Ђ' => 'ђ',
+ 'Ѓ' => 'ѓ',
+ 'Є' => 'є',
+ 'Ѕ' => 'ѕ',
+ 'І' => 'і',
+ 'Ї' => 'ї',
+ 'Ј' => 'ј',
+ 'Љ' => 'љ',
+ 'Њ' => 'њ',
+ 'Ћ' => 'ћ',
+ 'Ќ' => 'ќ',
+ 'Ѝ' => 'ѝ',
+ 'Ў' => 'ў',
+ 'Џ' => 'џ',
+ 'А' => 'а',
+ 'Б' => 'б',
+ 'В' => 'в',
+ 'Г' => 'г',
+ 'Д' => 'д',
+ 'Е' => 'е',
+ 'Ж' => 'ж',
+ 'З' => 'з',
+ 'И' => 'и',
+ 'Й' => 'й',
+ 'К' => 'к',
+ 'Л' => 'л',
+ 'М' => 'м',
+ 'Н' => 'н',
+ 'О' => 'о',
+ 'П' => 'п',
+ 'Р' => 'р',
+ 'С' => 'с',
+ 'Т' => 'т',
+ 'У' => 'у',
+ 'Ф' => 'ф',
+ 'Х' => 'х',
+ 'Ц' => 'ц',
+ 'Ч' => 'ч',
+ 'Ш' => 'ш',
+ 'Щ' => 'щ',
+ 'Ъ' => 'ъ',
+ 'Ы' => 'ы',
+ 'Ь' => 'ь',
+ 'Э' => 'э',
+ 'Ю' => 'ю',
+ 'Я' => 'я',
+ 'Ѡ' => 'ѡ',
+ 'Ѣ' => 'ѣ',
+ 'Ѥ' => 'ѥ',
+ 'Ѧ' => 'ѧ',
+ 'Ѩ' => 'ѩ',
+ 'Ѫ' => 'ѫ',
+ 'Ѭ' => 'ѭ',
+ 'Ѯ' => 'ѯ',
+ 'Ѱ' => 'ѱ',
+ 'Ѳ' => 'ѳ',
+ 'Ѵ' => 'ѵ',
+ 'Ѷ' => 'ѷ',
+ 'Ѹ' => 'ѹ',
+ 'Ѻ' => 'ѻ',
+ 'Ѽ' => 'ѽ',
+ 'Ѿ' => 'ѿ',
+ 'Ҁ' => 'ҁ',
+ 'Ҋ' => 'ҋ',
+ 'Ҍ' => 'ҍ',
+ 'Ҏ' => 'ҏ',
+ 'Ґ' => 'ґ',
+ 'Ғ' => 'ғ',
+ 'Ҕ' => 'ҕ',
+ 'Җ' => 'җ',
+ 'Ҙ' => 'ҙ',
+ 'Қ' => 'қ',
+ 'Ҝ' => 'ҝ',
+ 'Ҟ' => 'ҟ',
+ 'Ҡ' => 'ҡ',
+ 'Ң' => 'ң',
+ 'Ҥ' => 'ҥ',
+ 'Ҧ' => 'ҧ',
+ 'Ҩ' => 'ҩ',
+ 'Ҫ' => 'ҫ',
+ 'Ҭ' => 'ҭ',
+ 'Ү' => 'ү',
+ 'Ұ' => 'ұ',
+ 'Ҳ' => 'ҳ',
+ 'Ҵ' => 'ҵ',
+ 'Ҷ' => 'ҷ',
+ 'Ҹ' => 'ҹ',
+ 'Һ' => 'һ',
+ 'Ҽ' => 'ҽ',
+ 'Ҿ' => 'ҿ',
+ 'Ӏ' => 'ӏ',
+ 'Ӂ' => 'ӂ',
+ 'Ӄ' => 'ӄ',
+ 'Ӆ' => 'ӆ',
+ 'Ӈ' => 'ӈ',
+ 'Ӊ' => 'ӊ',
+ 'Ӌ' => 'ӌ',
+ 'Ӎ' => 'ӎ',
+ 'Ӑ' => 'ӑ',
+ 'Ӓ' => 'ӓ',
+ 'Ӕ' => 'ӕ',
+ 'Ӗ' => 'ӗ',
+ 'Ә' => 'ә',
+ 'Ӛ' => 'ӛ',
+ 'Ӝ' => 'ӝ',
+ 'Ӟ' => 'ӟ',
+ 'Ӡ' => 'ӡ',
+ 'Ӣ' => 'ӣ',
+ 'Ӥ' => 'ӥ',
+ 'Ӧ' => 'ӧ',
+ 'Ө' => 'ө',
+ 'Ӫ' => 'ӫ',
+ 'Ӭ' => 'ӭ',
+ 'Ӯ' => 'ӯ',
+ 'Ӱ' => 'ӱ',
+ 'Ӳ' => 'ӳ',
+ 'Ӵ' => 'ӵ',
+ 'Ӷ' => 'ӷ',
+ 'Ӹ' => 'ӹ',
+ 'Ӻ' => 'ӻ',
+ 'Ӽ' => 'ӽ',
+ 'Ӿ' => 'ӿ',
+ 'Ԁ' => 'ԁ',
+ 'Ԃ' => 'ԃ',
+ 'Ԅ' => 'ԅ',
+ 'Ԇ' => 'ԇ',
+ 'Ԉ' => 'ԉ',
+ 'Ԋ' => 'ԋ',
+ 'Ԍ' => 'ԍ',
+ 'Ԏ' => 'ԏ',
+ 'Ԑ' => 'ԑ',
+ 'Ԓ' => 'ԓ',
+ 'Ԕ' => 'ԕ',
+ 'Ԗ' => 'ԗ',
+ 'Ԙ' => 'ԙ',
+ 'Ԛ' => 'ԛ',
+ 'Ԝ' => 'ԝ',
+ 'Ԟ' => 'ԟ',
+ 'Ԡ' => 'ԡ',
+ 'Ԣ' => 'ԣ',
+ 'Ԥ' => 'ԥ',
+ 'Ԧ' => 'ԧ',
+ 'Ԩ' => 'ԩ',
+ 'Ԫ' => 'ԫ',
+ 'Ԭ' => 'ԭ',
+ 'Ԯ' => 'ԯ',
+ 'Ա' => 'ա',
+ 'Բ' => 'բ',
+ 'Գ' => 'գ',
+ 'Դ' => 'դ',
+ 'Ե' => 'ե',
+ 'Զ' => 'զ',
+ 'Է' => 'է',
+ 'Ը' => 'ը',
+ 'Թ' => 'թ',
+ 'Ժ' => 'ժ',
+ 'Ի' => 'ի',
+ 'Լ' => 'լ',
+ 'Խ' => 'խ',
+ 'Ծ' => 'ծ',
+ 'Կ' => 'կ',
+ 'Հ' => 'հ',
+ 'Ձ' => 'ձ',
+ 'Ղ' => 'ղ',
+ 'Ճ' => 'ճ',
+ 'Մ' => 'մ',
+ 'Յ' => 'յ',
+ 'Ն' => 'ն',
+ 'Շ' => 'շ',
+ 'Ո' => 'ո',
+ 'Չ' => 'չ',
+ 'Պ' => 'պ',
+ 'Ջ' => 'ջ',
+ 'Ռ' => 'ռ',
+ 'Ս' => 'ս',
+ 'Վ' => 'վ',
+ 'Տ' => 'տ',
+ 'Ր' => 'ր',
+ 'Ց' => 'ց',
+ 'Ւ' => 'ւ',
+ 'Փ' => 'փ',
+ 'Ք' => 'ք',
+ 'Օ' => 'օ',
+ 'Ֆ' => 'ֆ',
+ 'Ⴀ' => 'ⴀ',
+ 'Ⴁ' => 'ⴁ',
+ 'Ⴂ' => 'ⴂ',
+ 'Ⴃ' => 'ⴃ',
+ 'Ⴄ' => 'ⴄ',
+ 'Ⴅ' => 'ⴅ',
+ 'Ⴆ' => 'ⴆ',
+ 'Ⴇ' => 'ⴇ',
+ 'Ⴈ' => 'ⴈ',
+ 'Ⴉ' => 'ⴉ',
+ 'Ⴊ' => 'ⴊ',
+ 'Ⴋ' => 'ⴋ',
+ 'Ⴌ' => 'ⴌ',
+ 'Ⴍ' => 'ⴍ',
+ 'Ⴎ' => 'ⴎ',
+ 'Ⴏ' => 'ⴏ',
+ 'Ⴐ' => 'ⴐ',
+ 'Ⴑ' => 'ⴑ',
+ 'Ⴒ' => 'ⴒ',
+ 'Ⴓ' => 'ⴓ',
+ 'Ⴔ' => 'ⴔ',
+ 'Ⴕ' => 'ⴕ',
+ 'Ⴖ' => 'ⴖ',
+ 'Ⴗ' => 'ⴗ',
+ 'Ⴘ' => 'ⴘ',
+ 'Ⴙ' => 'ⴙ',
+ 'Ⴚ' => 'ⴚ',
+ 'Ⴛ' => 'ⴛ',
+ 'Ⴜ' => 'ⴜ',
+ 'Ⴝ' => 'ⴝ',
+ 'Ⴞ' => 'ⴞ',
+ 'Ⴟ' => 'ⴟ',
+ 'Ⴠ' => 'ⴠ',
+ 'Ⴡ' => 'ⴡ',
+ 'Ⴢ' => 'ⴢ',
+ 'Ⴣ' => 'ⴣ',
+ 'Ⴤ' => 'ⴤ',
+ 'Ⴥ' => 'ⴥ',
+ 'Ⴧ' => 'ⴧ',
+ 'Ⴭ' => 'ⴭ',
+ 'Ꭰ' => 'ꭰ',
+ 'Ꭱ' => 'ꭱ',
+ 'Ꭲ' => 'ꭲ',
+ 'Ꭳ' => 'ꭳ',
+ 'Ꭴ' => 'ꭴ',
+ 'Ꭵ' => 'ꭵ',
+ 'Ꭶ' => 'ꭶ',
+ 'Ꭷ' => 'ꭷ',
+ 'Ꭸ' => 'ꭸ',
+ 'Ꭹ' => 'ꭹ',
+ 'Ꭺ' => 'ꭺ',
+ 'Ꭻ' => 'ꭻ',
+ 'Ꭼ' => 'ꭼ',
+ 'Ꭽ' => 'ꭽ',
+ 'Ꭾ' => 'ꭾ',
+ 'Ꭿ' => 'ꭿ',
+ 'Ꮀ' => 'ꮀ',
+ 'Ꮁ' => 'ꮁ',
+ 'Ꮂ' => 'ꮂ',
+ 'Ꮃ' => 'ꮃ',
+ 'Ꮄ' => 'ꮄ',
+ 'Ꮅ' => 'ꮅ',
+ 'Ꮆ' => 'ꮆ',
+ 'Ꮇ' => 'ꮇ',
+ 'Ꮈ' => 'ꮈ',
+ 'Ꮉ' => 'ꮉ',
+ 'Ꮊ' => 'ꮊ',
+ 'Ꮋ' => 'ꮋ',
+ 'Ꮌ' => 'ꮌ',
+ 'Ꮍ' => 'ꮍ',
+ 'Ꮎ' => 'ꮎ',
+ 'Ꮏ' => 'ꮏ',
+ 'Ꮐ' => 'ꮐ',
+ 'Ꮑ' => 'ꮑ',
+ 'Ꮒ' => 'ꮒ',
+ 'Ꮓ' => 'ꮓ',
+ 'Ꮔ' => 'ꮔ',
+ 'Ꮕ' => 'ꮕ',
+ 'Ꮖ' => 'ꮖ',
+ 'Ꮗ' => 'ꮗ',
+ 'Ꮘ' => 'ꮘ',
+ 'Ꮙ' => 'ꮙ',
+ 'Ꮚ' => 'ꮚ',
+ 'Ꮛ' => 'ꮛ',
+ 'Ꮜ' => 'ꮜ',
+ 'Ꮝ' => 'ꮝ',
+ 'Ꮞ' => 'ꮞ',
+ 'Ꮟ' => 'ꮟ',
+ 'Ꮠ' => 'ꮠ',
+ 'Ꮡ' => 'ꮡ',
+ 'Ꮢ' => 'ꮢ',
+ 'Ꮣ' => 'ꮣ',
+ 'Ꮤ' => 'ꮤ',
+ 'Ꮥ' => 'ꮥ',
+ 'Ꮦ' => 'ꮦ',
+ 'Ꮧ' => 'ꮧ',
+ 'Ꮨ' => 'ꮨ',
+ 'Ꮩ' => 'ꮩ',
+ 'Ꮪ' => 'ꮪ',
+ 'Ꮫ' => 'ꮫ',
+ 'Ꮬ' => 'ꮬ',
+ 'Ꮭ' => 'ꮭ',
+ 'Ꮮ' => 'ꮮ',
+ 'Ꮯ' => 'ꮯ',
+ 'Ꮰ' => 'ꮰ',
+ 'Ꮱ' => 'ꮱ',
+ 'Ꮲ' => 'ꮲ',
+ 'Ꮳ' => 'ꮳ',
+ 'Ꮴ' => 'ꮴ',
+ 'Ꮵ' => 'ꮵ',
+ 'Ꮶ' => 'ꮶ',
+ 'Ꮷ' => 'ꮷ',
+ 'Ꮸ' => 'ꮸ',
+ 'Ꮹ' => 'ꮹ',
+ 'Ꮺ' => 'ꮺ',
+ 'Ꮻ' => 'ꮻ',
+ 'Ꮼ' => 'ꮼ',
+ 'Ꮽ' => 'ꮽ',
+ 'Ꮾ' => 'ꮾ',
+ 'Ꮿ' => 'ꮿ',
+ 'Ᏸ' => 'ᏸ',
+ 'Ᏹ' => 'ᏹ',
+ 'Ᏺ' => 'ᏺ',
+ 'Ᏻ' => 'ᏻ',
+ 'Ᏼ' => 'ᏼ',
+ 'Ᏽ' => 'ᏽ',
+ 'Ა' => 'ა',
+ 'Ბ' => 'ბ',
+ 'Გ' => 'გ',
+ 'Დ' => 'დ',
+ 'Ე' => 'ე',
+ 'Ვ' => 'ვ',
+ 'Ზ' => 'ზ',
+ 'Თ' => 'თ',
+ 'Ი' => 'ი',
+ 'Კ' => 'კ',
+ 'Ლ' => 'ლ',
+ 'Მ' => 'მ',
+ 'Ნ' => 'ნ',
+ 'Ო' => 'ო',
+ 'Პ' => 'პ',
+ 'Ჟ' => 'ჟ',
+ 'Რ' => 'რ',
+ 'Ს' => 'ს',
+ 'Ტ' => 'ტ',
+ 'Უ' => 'უ',
+ 'Ფ' => 'ფ',
+ 'Ქ' => 'ქ',
+ 'Ღ' => 'ღ',
+ 'Ყ' => 'ყ',
+ 'Შ' => 'შ',
+ 'Ჩ' => 'ჩ',
+ 'Ც' => 'ც',
+ 'Ძ' => 'ძ',
+ 'Წ' => 'წ',
+ 'Ჭ' => 'ჭ',
+ 'Ხ' => 'ხ',
+ 'Ჯ' => 'ჯ',
+ 'Ჰ' => 'ჰ',
+ 'Ჱ' => 'ჱ',
+ 'Ჲ' => 'ჲ',
+ 'Ჳ' => 'ჳ',
+ 'Ჴ' => 'ჴ',
+ 'Ჵ' => 'ჵ',
+ 'Ჶ' => 'ჶ',
+ 'Ჷ' => 'ჷ',
+ 'Ჸ' => 'ჸ',
+ 'Ჹ' => 'ჹ',
+ 'Ჺ' => 'ჺ',
+ 'Ჽ' => 'ჽ',
+ 'Ჾ' => 'ჾ',
+ 'Ჿ' => 'ჿ',
+ 'Ḁ' => 'ḁ',
+ 'Ḃ' => 'ḃ',
+ 'Ḅ' => 'ḅ',
+ 'Ḇ' => 'ḇ',
+ 'Ḉ' => 'ḉ',
+ 'Ḋ' => 'ḋ',
+ 'Ḍ' => 'ḍ',
+ 'Ḏ' => 'ḏ',
+ 'Ḑ' => 'ḑ',
+ 'Ḓ' => 'ḓ',
+ 'Ḕ' => 'ḕ',
+ 'Ḗ' => 'ḗ',
+ 'Ḙ' => 'ḙ',
+ 'Ḛ' => 'ḛ',
+ 'Ḝ' => 'ḝ',
+ 'Ḟ' => 'ḟ',
+ 'Ḡ' => 'ḡ',
+ 'Ḣ' => 'ḣ',
+ 'Ḥ' => 'ḥ',
+ 'Ḧ' => 'ḧ',
+ 'Ḩ' => 'ḩ',
+ 'Ḫ' => 'ḫ',
+ 'Ḭ' => 'ḭ',
+ 'Ḯ' => 'ḯ',
+ 'Ḱ' => 'ḱ',
+ 'Ḳ' => 'ḳ',
+ 'Ḵ' => 'ḵ',
+ 'Ḷ' => 'ḷ',
+ 'Ḹ' => 'ḹ',
+ 'Ḻ' => 'ḻ',
+ 'Ḽ' => 'ḽ',
+ 'Ḿ' => 'ḿ',
+ 'Ṁ' => 'ṁ',
+ 'Ṃ' => 'ṃ',
+ 'Ṅ' => 'ṅ',
+ 'Ṇ' => 'ṇ',
+ 'Ṉ' => 'ṉ',
+ 'Ṋ' => 'ṋ',
+ 'Ṍ' => 'ṍ',
+ 'Ṏ' => 'ṏ',
+ 'Ṑ' => 'ṑ',
+ 'Ṓ' => 'ṓ',
+ 'Ṕ' => 'ṕ',
+ 'Ṗ' => 'ṗ',
+ 'Ṙ' => 'ṙ',
+ 'Ṛ' => 'ṛ',
+ 'Ṝ' => 'ṝ',
+ 'Ṟ' => 'ṟ',
+ 'Ṡ' => 'ṡ',
+ 'Ṣ' => 'ṣ',
+ 'Ṥ' => 'ṥ',
+ 'Ṧ' => 'ṧ',
+ 'Ṩ' => 'ṩ',
+ 'Ṫ' => 'ṫ',
+ 'Ṭ' => 'ṭ',
+ 'Ṯ' => 'ṯ',
+ 'Ṱ' => 'ṱ',
+ 'Ṳ' => 'ṳ',
+ 'Ṵ' => 'ṵ',
+ 'Ṷ' => 'ṷ',
+ 'Ṹ' => 'ṹ',
+ 'Ṻ' => 'ṻ',
+ 'Ṽ' => 'ṽ',
+ 'Ṿ' => 'ṿ',
+ 'Ẁ' => 'ẁ',
+ 'Ẃ' => 'ẃ',
+ 'Ẅ' => 'ẅ',
+ 'Ẇ' => 'ẇ',
+ 'Ẉ' => 'ẉ',
+ 'Ẋ' => 'ẋ',
+ 'Ẍ' => 'ẍ',
+ 'Ẏ' => 'ẏ',
+ 'Ẑ' => 'ẑ',
+ 'Ẓ' => 'ẓ',
+ 'Ẕ' => 'ẕ',
+ 'ẞ' => 'ß',
+ 'Ạ' => 'ạ',
+ 'Ả' => 'ả',
+ 'Ấ' => 'ấ',
+ 'Ầ' => 'ầ',
+ 'Ẩ' => 'ẩ',
+ 'Ẫ' => 'ẫ',
+ 'Ậ' => 'ậ',
+ 'Ắ' => 'ắ',
+ 'Ằ' => 'ằ',
+ 'Ẳ' => 'ẳ',
+ 'Ẵ' => 'ẵ',
+ 'Ặ' => 'ặ',
+ 'Ẹ' => 'ẹ',
+ 'Ẻ' => 'ẻ',
+ 'Ẽ' => 'ẽ',
+ 'Ế' => 'ế',
+ 'Ề' => 'ề',
+ 'Ể' => 'ể',
+ 'Ễ' => 'ễ',
+ 'Ệ' => 'ệ',
+ 'Ỉ' => 'ỉ',
+ 'Ị' => 'ị',
+ 'Ọ' => 'ọ',
+ 'Ỏ' => 'ỏ',
+ 'Ố' => 'ố',
+ 'Ồ' => 'ồ',
+ 'Ổ' => 'ổ',
+ 'Ỗ' => 'ỗ',
+ 'Ộ' => 'ộ',
+ 'Ớ' => 'ớ',
+ 'Ờ' => 'ờ',
+ 'Ở' => 'ở',
+ 'Ỡ' => 'ỡ',
+ 'Ợ' => 'ợ',
+ 'Ụ' => 'ụ',
+ 'Ủ' => 'ủ',
+ 'Ứ' => 'ứ',
+ 'Ừ' => 'ừ',
+ 'Ử' => 'ử',
+ 'Ữ' => 'ữ',
+ 'Ự' => 'ự',
+ 'Ỳ' => 'ỳ',
+ 'Ỵ' => 'ỵ',
+ 'Ỷ' => 'ỷ',
+ 'Ỹ' => 'ỹ',
+ 'Ỻ' => 'ỻ',
+ 'Ỽ' => 'ỽ',
+ 'Ỿ' => 'ỿ',
+ 'Ἀ' => 'ἀ',
+ 'Ἁ' => 'ἁ',
+ 'Ἂ' => 'ἂ',
+ 'Ἃ' => 'ἃ',
+ 'Ἄ' => 'ἄ',
+ 'Ἅ' => 'ἅ',
+ 'Ἆ' => 'ἆ',
+ 'Ἇ' => 'ἇ',
+ 'Ἐ' => 'ἐ',
+ 'Ἑ' => 'ἑ',
+ 'Ἒ' => 'ἒ',
+ 'Ἓ' => 'ἓ',
+ 'Ἔ' => 'ἔ',
+ 'Ἕ' => 'ἕ',
+ 'Ἠ' => 'ἠ',
+ 'Ἡ' => 'ἡ',
+ 'Ἢ' => 'ἢ',
+ 'Ἣ' => 'ἣ',
+ 'Ἤ' => 'ἤ',
+ 'Ἥ' => 'ἥ',
+ 'Ἦ' => 'ἦ',
+ 'Ἧ' => 'ἧ',
+ 'Ἰ' => 'ἰ',
+ 'Ἱ' => 'ἱ',
+ 'Ἲ' => 'ἲ',
+ 'Ἳ' => 'ἳ',
+ 'Ἴ' => 'ἴ',
+ 'Ἵ' => 'ἵ',
+ 'Ἶ' => 'ἶ',
+ 'Ἷ' => 'ἷ',
+ 'Ὀ' => 'ὀ',
+ 'Ὁ' => 'ὁ',
+ 'Ὂ' => 'ὂ',
+ 'Ὃ' => 'ὃ',
+ 'Ὄ' => 'ὄ',
+ 'Ὅ' => 'ὅ',
+ 'Ὑ' => 'ὑ',
+ 'Ὓ' => 'ὓ',
+ 'Ὕ' => 'ὕ',
+ 'Ὗ' => 'ὗ',
+ 'Ὠ' => 'ὠ',
+ 'Ὡ' => 'ὡ',
+ 'Ὢ' => 'ὢ',
+ 'Ὣ' => 'ὣ',
+ 'Ὤ' => 'ὤ',
+ 'Ὥ' => 'ὥ',
+ 'Ὦ' => 'ὦ',
+ 'Ὧ' => 'ὧ',
+ 'ᾈ' => 'ᾀ',
+ 'ᾉ' => 'ᾁ',
+ 'ᾊ' => 'ᾂ',
+ 'ᾋ' => 'ᾃ',
+ 'ᾌ' => 'ᾄ',
+ 'ᾍ' => 'ᾅ',
+ 'ᾎ' => 'ᾆ',
+ 'ᾏ' => 'ᾇ',
+ 'ᾘ' => 'ᾐ',
+ 'ᾙ' => 'ᾑ',
+ 'ᾚ' => 'ᾒ',
+ 'ᾛ' => 'ᾓ',
+ 'ᾜ' => 'ᾔ',
+ 'ᾝ' => 'ᾕ',
+ 'ᾞ' => 'ᾖ',
+ 'ᾟ' => 'ᾗ',
+ 'ᾨ' => 'ᾠ',
+ 'ᾩ' => 'ᾡ',
+ 'ᾪ' => 'ᾢ',
+ 'ᾫ' => 'ᾣ',
+ 'ᾬ' => 'ᾤ',
+ 'ᾭ' => 'ᾥ',
+ 'ᾮ' => 'ᾦ',
+ 'ᾯ' => 'ᾧ',
+ 'Ᾰ' => 'ᾰ',
+ 'Ᾱ' => 'ᾱ',
+ 'Ὰ' => 'ὰ',
+ 'Ά' => 'ά',
+ 'ᾼ' => 'ᾳ',
+ 'Ὲ' => 'ὲ',
+ 'Έ' => 'έ',
+ 'Ὴ' => 'ὴ',
+ 'Ή' => 'ή',
+ 'ῌ' => 'ῃ',
+ 'Ῐ' => 'ῐ',
+ 'Ῑ' => 'ῑ',
+ 'Ὶ' => 'ὶ',
+ 'Ί' => 'ί',
+ 'Ῠ' => 'ῠ',
+ 'Ῡ' => 'ῡ',
+ 'Ὺ' => 'ὺ',
+ 'Ύ' => 'ύ',
+ 'Ῥ' => 'ῥ',
+ 'Ὸ' => 'ὸ',
+ 'Ό' => 'ό',
+ 'Ὼ' => 'ὼ',
+ 'Ώ' => 'ώ',
+ 'ῼ' => 'ῳ',
+ 'Ω' => 'ω',
+ 'K' => 'k',
+ 'Å' => 'å',
+ 'Ⅎ' => 'ⅎ',
+ 'Ⅰ' => 'ⅰ',
+ 'Ⅱ' => 'ⅱ',
+ 'Ⅲ' => 'ⅲ',
+ 'Ⅳ' => 'ⅳ',
+ 'Ⅴ' => 'ⅴ',
+ 'Ⅵ' => 'ⅵ',
+ 'Ⅶ' => 'ⅶ',
+ 'Ⅷ' => 'ⅷ',
+ 'Ⅸ' => 'ⅸ',
+ 'Ⅹ' => 'ⅹ',
+ 'Ⅺ' => 'ⅺ',
+ 'Ⅻ' => 'ⅻ',
+ 'Ⅼ' => 'ⅼ',
+ 'Ⅽ' => 'ⅽ',
+ 'Ⅾ' => 'ⅾ',
+ 'Ⅿ' => 'ⅿ',
+ 'Ↄ' => 'ↄ',
+ 'Ⓐ' => 'ⓐ',
+ 'Ⓑ' => 'ⓑ',
+ 'Ⓒ' => 'ⓒ',
+ 'Ⓓ' => 'ⓓ',
+ 'Ⓔ' => 'ⓔ',
+ 'Ⓕ' => 'ⓕ',
+ 'Ⓖ' => 'ⓖ',
+ 'Ⓗ' => 'ⓗ',
+ 'Ⓘ' => 'ⓘ',
+ 'Ⓙ' => 'ⓙ',
+ 'Ⓚ' => 'ⓚ',
+ 'Ⓛ' => 'ⓛ',
+ 'Ⓜ' => 'ⓜ',
+ 'Ⓝ' => 'ⓝ',
+ 'Ⓞ' => 'ⓞ',
+ 'Ⓟ' => 'ⓟ',
+ 'Ⓠ' => 'ⓠ',
+ 'Ⓡ' => 'ⓡ',
+ 'Ⓢ' => 'ⓢ',
+ 'Ⓣ' => 'ⓣ',
+ 'Ⓤ' => 'ⓤ',
+ 'Ⓥ' => 'ⓥ',
+ 'Ⓦ' => 'ⓦ',
+ 'Ⓧ' => 'ⓧ',
+ 'Ⓨ' => 'ⓨ',
+ 'Ⓩ' => 'ⓩ',
+ 'Ⰰ' => 'ⰰ',
+ 'Ⰱ' => 'ⰱ',
+ 'Ⰲ' => 'ⰲ',
+ 'Ⰳ' => 'ⰳ',
+ 'Ⰴ' => 'ⰴ',
+ 'Ⰵ' => 'ⰵ',
+ 'Ⰶ' => 'ⰶ',
+ 'Ⰷ' => 'ⰷ',
+ 'Ⰸ' => 'ⰸ',
+ 'Ⰹ' => 'ⰹ',
+ 'Ⰺ' => 'ⰺ',
+ 'Ⰻ' => 'ⰻ',
+ 'Ⰼ' => 'ⰼ',
+ 'Ⰽ' => 'ⰽ',
+ 'Ⰾ' => 'ⰾ',
+ 'Ⰿ' => 'ⰿ',
+ 'Ⱀ' => 'ⱀ',
+ 'Ⱁ' => 'ⱁ',
+ 'Ⱂ' => 'ⱂ',
+ 'Ⱃ' => 'ⱃ',
+ 'Ⱄ' => 'ⱄ',
+ 'Ⱅ' => 'ⱅ',
+ 'Ⱆ' => 'ⱆ',
+ 'Ⱇ' => 'ⱇ',
+ 'Ⱈ' => 'ⱈ',
+ 'Ⱉ' => 'ⱉ',
+ 'Ⱊ' => 'ⱊ',
+ 'Ⱋ' => 'ⱋ',
+ 'Ⱌ' => 'ⱌ',
+ 'Ⱍ' => 'ⱍ',
+ 'Ⱎ' => 'ⱎ',
+ 'Ⱏ' => 'ⱏ',
+ 'Ⱐ' => 'ⱐ',
+ 'Ⱑ' => 'ⱑ',
+ 'Ⱒ' => 'ⱒ',
+ 'Ⱓ' => 'ⱓ',
+ 'Ⱔ' => 'ⱔ',
+ 'Ⱕ' => 'ⱕ',
+ 'Ⱖ' => 'ⱖ',
+ 'Ⱗ' => 'ⱗ',
+ 'Ⱘ' => 'ⱘ',
+ 'Ⱙ' => 'ⱙ',
+ 'Ⱚ' => 'ⱚ',
+ 'Ⱛ' => 'ⱛ',
+ 'Ⱜ' => 'ⱜ',
+ 'Ⱝ' => 'ⱝ',
+ 'Ⱞ' => 'ⱞ',
+ 'Ⱡ' => 'ⱡ',
+ 'Ɫ' => 'ɫ',
+ 'Ᵽ' => 'ᵽ',
+ 'Ɽ' => 'ɽ',
+ 'Ⱨ' => 'ⱨ',
+ 'Ⱪ' => 'ⱪ',
+ 'Ⱬ' => 'ⱬ',
+ 'Ɑ' => 'ɑ',
+ 'Ɱ' => 'ɱ',
+ 'Ɐ' => 'ɐ',
+ 'Ɒ' => 'ɒ',
+ 'Ⱳ' => 'ⱳ',
+ 'Ⱶ' => 'ⱶ',
+ 'Ȿ' => 'ȿ',
+ 'Ɀ' => 'ɀ',
+ 'Ⲁ' => 'ⲁ',
+ 'Ⲃ' => 'ⲃ',
+ 'Ⲅ' => 'ⲅ',
+ 'Ⲇ' => 'ⲇ',
+ 'Ⲉ' => 'ⲉ',
+ 'Ⲋ' => 'ⲋ',
+ 'Ⲍ' => 'ⲍ',
+ 'Ⲏ' => 'ⲏ',
+ 'Ⲑ' => 'ⲑ',
+ 'Ⲓ' => 'ⲓ',
+ 'Ⲕ' => 'ⲕ',
+ 'Ⲗ' => 'ⲗ',
+ 'Ⲙ' => 'ⲙ',
+ 'Ⲛ' => 'ⲛ',
+ 'Ⲝ' => 'ⲝ',
+ 'Ⲟ' => 'ⲟ',
+ 'Ⲡ' => 'ⲡ',
+ 'Ⲣ' => 'ⲣ',
+ 'Ⲥ' => 'ⲥ',
+ 'Ⲧ' => 'ⲧ',
+ 'Ⲩ' => 'ⲩ',
+ 'Ⲫ' => 'ⲫ',
+ 'Ⲭ' => 'ⲭ',
+ 'Ⲯ' => 'ⲯ',
+ 'Ⲱ' => 'ⲱ',
+ 'Ⲳ' => 'ⲳ',
+ 'Ⲵ' => 'ⲵ',
+ 'Ⲷ' => 'ⲷ',
+ 'Ⲹ' => 'ⲹ',
+ 'Ⲻ' => 'ⲻ',
+ 'Ⲽ' => 'ⲽ',
+ 'Ⲿ' => 'ⲿ',
+ 'Ⳁ' => 'ⳁ',
+ 'Ⳃ' => 'ⳃ',
+ 'Ⳅ' => 'ⳅ',
+ 'Ⳇ' => 'ⳇ',
+ 'Ⳉ' => 'ⳉ',
+ 'Ⳋ' => 'ⳋ',
+ 'Ⳍ' => 'ⳍ',
+ 'Ⳏ' => 'ⳏ',
+ 'Ⳑ' => 'ⳑ',
+ 'Ⳓ' => 'ⳓ',
+ 'Ⳕ' => 'ⳕ',
+ 'Ⳗ' => 'ⳗ',
+ 'Ⳙ' => 'ⳙ',
+ 'Ⳛ' => 'ⳛ',
+ 'Ⳝ' => 'ⳝ',
+ 'Ⳟ' => 'ⳟ',
+ 'Ⳡ' => 'ⳡ',
+ 'Ⳣ' => 'ⳣ',
+ 'Ⳬ' => 'ⳬ',
+ 'Ⳮ' => 'ⳮ',
+ 'Ⳳ' => 'ⳳ',
+ 'Ꙁ' => 'ꙁ',
+ 'Ꙃ' => 'ꙃ',
+ 'Ꙅ' => 'ꙅ',
+ 'Ꙇ' => 'ꙇ',
+ 'Ꙉ' => 'ꙉ',
+ 'Ꙋ' => 'ꙋ',
+ 'Ꙍ' => 'ꙍ',
+ 'Ꙏ' => 'ꙏ',
+ 'Ꙑ' => 'ꙑ',
+ 'Ꙓ' => 'ꙓ',
+ 'Ꙕ' => 'ꙕ',
+ 'Ꙗ' => 'ꙗ',
+ 'Ꙙ' => 'ꙙ',
+ 'Ꙛ' => 'ꙛ',
+ 'Ꙝ' => 'ꙝ',
+ 'Ꙟ' => 'ꙟ',
+ 'Ꙡ' => 'ꙡ',
+ 'Ꙣ' => 'ꙣ',
+ 'Ꙥ' => 'ꙥ',
+ 'Ꙧ' => 'ꙧ',
+ 'Ꙩ' => 'ꙩ',
+ 'Ꙫ' => 'ꙫ',
+ 'Ꙭ' => 'ꙭ',
+ 'Ꚁ' => 'ꚁ',
+ 'Ꚃ' => 'ꚃ',
+ 'Ꚅ' => 'ꚅ',
+ 'Ꚇ' => 'ꚇ',
+ 'Ꚉ' => 'ꚉ',
+ 'Ꚋ' => 'ꚋ',
+ 'Ꚍ' => 'ꚍ',
+ 'Ꚏ' => 'ꚏ',
+ 'Ꚑ' => 'ꚑ',
+ 'Ꚓ' => 'ꚓ',
+ 'Ꚕ' => 'ꚕ',
+ 'Ꚗ' => 'ꚗ',
+ 'Ꚙ' => 'ꚙ',
+ 'Ꚛ' => 'ꚛ',
+ 'Ꜣ' => 'ꜣ',
+ 'Ꜥ' => 'ꜥ',
+ 'Ꜧ' => 'ꜧ',
+ 'Ꜩ' => 'ꜩ',
+ 'Ꜫ' => 'ꜫ',
+ 'Ꜭ' => 'ꜭ',
+ 'Ꜯ' => 'ꜯ',
+ 'Ꜳ' => 'ꜳ',
+ 'Ꜵ' => 'ꜵ',
+ 'Ꜷ' => 'ꜷ',
+ 'Ꜹ' => 'ꜹ',
+ 'Ꜻ' => 'ꜻ',
+ 'Ꜽ' => 'ꜽ',
+ 'Ꜿ' => 'ꜿ',
+ 'Ꝁ' => 'ꝁ',
+ 'Ꝃ' => 'ꝃ',
+ 'Ꝅ' => 'ꝅ',
+ 'Ꝇ' => 'ꝇ',
+ 'Ꝉ' => 'ꝉ',
+ 'Ꝋ' => 'ꝋ',
+ 'Ꝍ' => 'ꝍ',
+ 'Ꝏ' => 'ꝏ',
+ 'Ꝑ' => 'ꝑ',
+ 'Ꝓ' => 'ꝓ',
+ 'Ꝕ' => 'ꝕ',
+ 'Ꝗ' => 'ꝗ',
+ 'Ꝙ' => 'ꝙ',
+ 'Ꝛ' => 'ꝛ',
+ 'Ꝝ' => 'ꝝ',
+ 'Ꝟ' => 'ꝟ',
+ 'Ꝡ' => 'ꝡ',
+ 'Ꝣ' => 'ꝣ',
+ 'Ꝥ' => 'ꝥ',
+ 'Ꝧ' => 'ꝧ',
+ 'Ꝩ' => 'ꝩ',
+ 'Ꝫ' => 'ꝫ',
+ 'Ꝭ' => 'ꝭ',
+ 'Ꝯ' => 'ꝯ',
+ 'Ꝺ' => 'ꝺ',
+ 'Ꝼ' => 'ꝼ',
+ 'Ᵹ' => 'ᵹ',
+ 'Ꝿ' => 'ꝿ',
+ 'Ꞁ' => 'ꞁ',
+ 'Ꞃ' => 'ꞃ',
+ 'Ꞅ' => 'ꞅ',
+ 'Ꞇ' => 'ꞇ',
+ 'Ꞌ' => 'ꞌ',
+ 'Ɥ' => 'ɥ',
+ 'Ꞑ' => 'ꞑ',
+ 'Ꞓ' => 'ꞓ',
+ 'Ꞗ' => 'ꞗ',
+ 'Ꞙ' => 'ꞙ',
+ 'Ꞛ' => 'ꞛ',
+ 'Ꞝ' => 'ꞝ',
+ 'Ꞟ' => 'ꞟ',
+ 'Ꞡ' => 'ꞡ',
+ 'Ꞣ' => 'ꞣ',
+ 'Ꞥ' => 'ꞥ',
+ 'Ꞧ' => 'ꞧ',
+ 'Ꞩ' => 'ꞩ',
+ 'Ɦ' => 'ɦ',
+ 'Ɜ' => 'ɜ',
+ 'Ɡ' => 'ɡ',
+ 'Ɬ' => 'ɬ',
+ 'Ɪ' => 'ɪ',
+ 'Ʞ' => 'ʞ',
+ 'Ʇ' => 'ʇ',
+ 'Ʝ' => 'ʝ',
+ 'Ꭓ' => 'ꭓ',
+ 'Ꞵ' => 'ꞵ',
+ 'Ꞷ' => 'ꞷ',
+ 'Ꞹ' => 'ꞹ',
+ 'Ꞻ' => 'ꞻ',
+ 'Ꞽ' => 'ꞽ',
+ 'Ꞿ' => 'ꞿ',
+ 'Ꟃ' => 'ꟃ',
+ 'Ꞔ' => 'ꞔ',
+ 'Ʂ' => 'ʂ',
+ 'Ᶎ' => 'ᶎ',
+ 'Ꟈ' => 'ꟈ',
+ 'Ꟊ' => 'ꟊ',
+ 'Ꟶ' => 'ꟶ',
+ 'A' => 'a',
+ 'B' => 'b',
+ 'C' => 'c',
+ 'D' => 'd',
+ 'E' => 'e',
+ 'F' => 'f',
+ 'G' => 'g',
+ 'H' => 'h',
+ 'I' => 'i',
+ 'J' => 'j',
+ 'K' => 'k',
+ 'L' => 'l',
+ 'M' => 'm',
+ 'N' => 'n',
+ 'O' => 'o',
+ 'P' => 'p',
+ 'Q' => 'q',
+ 'R' => 'r',
+ 'S' => 's',
+ 'T' => 't',
+ 'U' => 'u',
+ 'V' => 'v',
+ 'W' => 'w',
+ 'X' => 'x',
+ 'Y' => 'y',
+ 'Z' => 'z',
+ '𐐀' => '𐐨',
+ '𐐁' => '𐐩',
+ '𐐂' => '𐐪',
+ '𐐃' => '𐐫',
+ '𐐄' => '𐐬',
+ '𐐅' => '𐐭',
+ '𐐆' => '𐐮',
+ '𐐇' => '𐐯',
+ '𐐈' => '𐐰',
+ '𐐉' => '𐐱',
+ '𐐊' => '𐐲',
+ '𐐋' => '𐐳',
+ '𐐌' => '𐐴',
+ '𐐍' => '𐐵',
+ '𐐎' => '𐐶',
+ '𐐏' => '𐐷',
+ '𐐐' => '𐐸',
+ '𐐑' => '𐐹',
+ '𐐒' => '𐐺',
+ '𐐓' => '𐐻',
+ '𐐔' => '𐐼',
+ '𐐕' => '𐐽',
+ '𐐖' => '𐐾',
+ '𐐗' => '𐐿',
+ '𐐘' => '𐑀',
+ '𐐙' => '𐑁',
+ '𐐚' => '𐑂',
+ '𐐛' => '𐑃',
+ '𐐜' => '𐑄',
+ '𐐝' => '𐑅',
+ '𐐞' => '𐑆',
+ '𐐟' => '𐑇',
+ '𐐠' => '𐑈',
+ '𐐡' => '𐑉',
+ '𐐢' => '𐑊',
+ '𐐣' => '𐑋',
+ '𐐤' => '𐑌',
+ '𐐥' => '𐑍',
+ '𐐦' => '𐑎',
+ '𐐧' => '𐑏',
+ '𐒰' => '𐓘',
+ '𐒱' => '𐓙',
+ '𐒲' => '𐓚',
+ '𐒳' => '𐓛',
+ '𐒴' => '𐓜',
+ '𐒵' => '𐓝',
+ '𐒶' => '𐓞',
+ '𐒷' => '𐓟',
+ '𐒸' => '𐓠',
+ '𐒹' => '𐓡',
+ '𐒺' => '𐓢',
+ '𐒻' => '𐓣',
+ '𐒼' => '𐓤',
+ '𐒽' => '𐓥',
+ '𐒾' => '𐓦',
+ '𐒿' => '𐓧',
+ '𐓀' => '𐓨',
+ '𐓁' => '𐓩',
+ '𐓂' => '𐓪',
+ '𐓃' => '𐓫',
+ '𐓄' => '𐓬',
+ '𐓅' => '𐓭',
+ '𐓆' => '𐓮',
+ '𐓇' => '𐓯',
+ '𐓈' => '𐓰',
+ '𐓉' => '𐓱',
+ '𐓊' => '𐓲',
+ '𐓋' => '𐓳',
+ '𐓌' => '𐓴',
+ '𐓍' => '𐓵',
+ '𐓎' => '𐓶',
+ '𐓏' => '𐓷',
+ '𐓐' => '𐓸',
+ '𐓑' => '𐓹',
+ '𐓒' => '𐓺',
+ '𐓓' => '𐓻',
+ '𐲀' => '𐳀',
+ '𐲁' => '𐳁',
+ '𐲂' => '𐳂',
+ '𐲃' => '𐳃',
+ '𐲄' => '𐳄',
+ '𐲅' => '𐳅',
+ '𐲆' => '𐳆',
+ '𐲇' => '𐳇',
+ '𐲈' => '𐳈',
+ '𐲉' => '𐳉',
+ '𐲊' => '𐳊',
+ '𐲋' => '𐳋',
+ '𐲌' => '𐳌',
+ '𐲍' => '𐳍',
+ '𐲎' => '𐳎',
+ '𐲏' => '𐳏',
+ '𐲐' => '𐳐',
+ '𐲑' => '𐳑',
+ '𐲒' => '𐳒',
+ '𐲓' => '𐳓',
+ '𐲔' => '𐳔',
+ '𐲕' => '𐳕',
+ '𐲖' => '𐳖',
+ '𐲗' => '𐳗',
+ '𐲘' => '𐳘',
+ '𐲙' => '𐳙',
+ '𐲚' => '𐳚',
+ '𐲛' => '𐳛',
+ '𐲜' => '𐳜',
+ '𐲝' => '𐳝',
+ '𐲞' => '𐳞',
+ '𐲟' => '𐳟',
+ '𐲠' => '𐳠',
+ '𐲡' => '𐳡',
+ '𐲢' => '𐳢',
+ '𐲣' => '𐳣',
+ '𐲤' => '𐳤',
+ '𐲥' => '𐳥',
+ '𐲦' => '𐳦',
+ '𐲧' => '𐳧',
+ '𐲨' => '𐳨',
+ '𐲩' => '𐳩',
+ '𐲪' => '𐳪',
+ '𐲫' => '𐳫',
+ '𐲬' => '𐳬',
+ '𐲭' => '𐳭',
+ '𐲮' => '𐳮',
+ '𐲯' => '𐳯',
+ '𐲰' => '𐳰',
+ '𐲱' => '𐳱',
+ '𐲲' => '𐳲',
+ '𑢠' => '𑣀',
+ '𑢡' => '𑣁',
+ '𑢢' => '𑣂',
+ '𑢣' => '𑣃',
+ '𑢤' => '𑣄',
+ '𑢥' => '𑣅',
+ '𑢦' => '𑣆',
+ '𑢧' => '𑣇',
+ '𑢨' => '𑣈',
+ '𑢩' => '𑣉',
+ '𑢪' => '𑣊',
+ '𑢫' => '𑣋',
+ '𑢬' => '𑣌',
+ '𑢭' => '𑣍',
+ '𑢮' => '𑣎',
+ '𑢯' => '𑣏',
+ '𑢰' => '𑣐',
+ '𑢱' => '𑣑',
+ '𑢲' => '𑣒',
+ '𑢳' => '𑣓',
+ '𑢴' => '𑣔',
+ '𑢵' => '𑣕',
+ '𑢶' => '𑣖',
+ '𑢷' => '𑣗',
+ '𑢸' => '𑣘',
+ '𑢹' => '𑣙',
+ '𑢺' => '𑣚',
+ '𑢻' => '𑣛',
+ '𑢼' => '𑣜',
+ '𑢽' => '𑣝',
+ '𑢾' => '𑣞',
+ '𑢿' => '𑣟',
+ '𖹀' => '𖹠',
+ '𖹁' => '𖹡',
+ '𖹂' => '𖹢',
+ '𖹃' => '𖹣',
+ '𖹄' => '𖹤',
+ '𖹅' => '𖹥',
+ '𖹆' => '𖹦',
+ '𖹇' => '𖹧',
+ '𖹈' => '𖹨',
+ '𖹉' => '𖹩',
+ '𖹊' => '𖹪',
+ '𖹋' => '𖹫',
+ '𖹌' => '𖹬',
+ '𖹍' => '𖹭',
+ '𖹎' => '𖹮',
+ '𖹏' => '𖹯',
+ '𖹐' => '𖹰',
+ '𖹑' => '𖹱',
+ '𖹒' => '𖹲',
+ '𖹓' => '𖹳',
+ '𖹔' => '𖹴',
+ '𖹕' => '𖹵',
+ '𖹖' => '𖹶',
+ '𖹗' => '𖹷',
+ '𖹘' => '𖹸',
+ '𖹙' => '𖹹',
+ '𖹚' => '𖹺',
+ '𖹛' => '𖹻',
+ '𖹜' => '𖹼',
+ '𖹝' => '𖹽',
+ '𖹞' => '𖹾',
+ '𖹟' => '𖹿',
+ '𞤀' => '𞤢',
+ '𞤁' => '𞤣',
+ '𞤂' => '𞤤',
+ '𞤃' => '𞤥',
+ '𞤄' => '𞤦',
+ '𞤅' => '𞤧',
+ '𞤆' => '𞤨',
+ '𞤇' => '𞤩',
+ '𞤈' => '𞤪',
+ '𞤉' => '𞤫',
+ '𞤊' => '𞤬',
+ '𞤋' => '𞤭',
+ '𞤌' => '𞤮',
+ '𞤍' => '𞤯',
+ '𞤎' => '𞤰',
+ '𞤏' => '𞤱',
+ '𞤐' => '𞤲',
+ '𞤑' => '𞤳',
+ '𞤒' => '𞤴',
+ '𞤓' => '𞤵',
+ '𞤔' => '𞤶',
+ '𞤕' => '𞤷',
+ '𞤖' => '𞤸',
+ '𞤗' => '𞤹',
+ '𞤘' => '𞤺',
+ '𞤙' => '𞤻',
+ '𞤚' => '𞤼',
+ '𞤛' => '𞤽',
+ '𞤜' => '𞤾',
+ '𞤝' => '𞤿',
+ '𞤞' => '𞥀',
+ '𞤟' => '𞥁',
+ '𞤠' => '𞥂',
+ '𞤡' => '𞥃',
+);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php
new file mode 100644
index 0000000..2a8f6e7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php
@@ -0,0 +1,5 @@
+<?php
+
+// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt
+
+return '/(?<![\x{0027}\x{002E}\x{003A}\x{005E}\x{0060}\x{00A8}\x{00AD}\x{00AF}\x{00B4}\x{00B7}\x{00B8}\x{02B0}-\x{02C1}\x{02C2}-\x{02C5}\x{02C6}-\x{02D1}\x{02D2}-\x{02DF}\x{02E0}-\x{02E4}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EE}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037A}\x{0384}-\x{0385}\x{0387}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0559}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{05F4}\x{0600}-\x{0605}\x{0610}-\x{061A}\x{061C}\x{0640}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DD}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07FA}\x{07FD}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0971}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E46}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}\x{0EBB}-\x{0EBC}\x{0EC6}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{10FC}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17D7}\x{17DD}\x{180B}-\x{180D}\x{180E}\x{1843}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AA7}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1C78}-\x{1C7D}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1D2C}-\x{1D6A}\x{1D78}\x{1D9B}-\x{1DBF}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200F}\x{2018}\x{2019}\x{2024}\x{2027}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{206F}\x{2071}\x{207F}\x{2090}-\x{209C}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2C7C}-\x{2C7D}\x{2CEF}-\x{2CF1}\x{2D6F}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E2F}\x{3005}\x{302A}-\x{302D}\x{3031}-\x{3035}\x{303B}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{309D}-\x{309E}\x{30FC}-\x{30FE}\x{A015}\x{A4F8}-\x{A4FD}\x{A60C}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A67F}\x{A69C}-\x{A69D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A770}\x{A788}\x{A789}-\x{A78A}\x{A7F8}-\x{A7F9}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}\x{A9CF}\x{A9E5}\x{A9E6}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA70}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AADD}\x{AAEC}-\x{AAED}\x{AAF3}-\x{AAF4}\x{AAF6}\x{AB5B}\x{AB5C}-\x{AB5F}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FBB2}-\x{FBC1}\x{FE00}-\x{FE0F}\x{FE13}\x{FE20}-\x{FE2F}\x{FE52}\x{FE55}\x{FEFF}\x{FF07}\x{FF0E}\x{FF1A}\x{FF3E}\x{FF40}\x{FF70}\x{FF9E}-\x{FF9F}\x{FFE3}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{110BD}\x{110CD}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16B40}-\x{16B43}\x{16F8F}-\x{16F92}\x{16F93}-\x{16F9F}\x{16FE0}-\x{16FE1}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1F3FB}-\x{1F3FF}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}])(\pL)(\pL*+)/u';
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
new file mode 100644
index 0000000..56b9cb8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
@@ -0,0 +1,1489 @@
+<?php
+
+return array (
+ 'a' => 'A',
+ 'b' => 'B',
+ 'c' => 'C',
+ 'd' => 'D',
+ 'e' => 'E',
+ 'f' => 'F',
+ 'g' => 'G',
+ 'h' => 'H',
+ 'i' => 'I',
+ 'j' => 'J',
+ 'k' => 'K',
+ 'l' => 'L',
+ 'm' => 'M',
+ 'n' => 'N',
+ 'o' => 'O',
+ 'p' => 'P',
+ 'q' => 'Q',
+ 'r' => 'R',
+ 's' => 'S',
+ 't' => 'T',
+ 'u' => 'U',
+ 'v' => 'V',
+ 'w' => 'W',
+ 'x' => 'X',
+ 'y' => 'Y',
+ 'z' => 'Z',
+ 'µ' => 'Μ',
+ 'à' => 'À',
+ 'á' => 'Á',
+ 'â' => 'Â',
+ 'ã' => 'Ã',
+ 'ä' => 'Ä',
+ 'å' => 'Å',
+ 'æ' => 'Æ',
+ 'ç' => 'Ç',
+ 'è' => 'È',
+ 'é' => 'É',
+ 'ê' => 'Ê',
+ 'ë' => 'Ë',
+ 'ì' => 'Ì',
+ 'í' => 'Í',
+ 'î' => 'Î',
+ 'ï' => 'Ï',
+ 'ð' => 'Ð',
+ 'ñ' => 'Ñ',
+ 'ò' => 'Ò',
+ 'ó' => 'Ó',
+ 'ô' => 'Ô',
+ 'õ' => 'Õ',
+ 'ö' => 'Ö',
+ 'ø' => 'Ø',
+ 'ù' => 'Ù',
+ 'ú' => 'Ú',
+ 'û' => 'Û',
+ 'ü' => 'Ü',
+ 'ý' => 'Ý',
+ 'þ' => 'Þ',
+ 'ÿ' => 'Ÿ',
+ 'ā' => 'Ā',
+ 'ă' => 'Ă',
+ 'ą' => 'Ą',
+ 'ć' => 'Ć',
+ 'ĉ' => 'Ĉ',
+ 'ċ' => 'Ċ',
+ 'č' => 'Č',
+ 'ď' => 'Ď',
+ 'đ' => 'Đ',
+ 'ē' => 'Ē',
+ 'ĕ' => 'Ĕ',
+ 'ė' => 'Ė',
+ 'ę' => 'Ę',
+ 'ě' => 'Ě',
+ 'ĝ' => 'Ĝ',
+ 'ğ' => 'Ğ',
+ 'ġ' => 'Ġ',
+ 'ģ' => 'Ģ',
+ 'ĥ' => 'Ĥ',
+ 'ħ' => 'Ħ',
+ 'ĩ' => 'Ĩ',
+ 'ī' => 'Ī',
+ 'ĭ' => 'Ĭ',
+ 'į' => 'Į',
+ 'ı' => 'I',
+ 'ij' => 'IJ',
+ 'ĵ' => 'Ĵ',
+ 'ķ' => 'Ķ',
+ 'ĺ' => 'Ĺ',
+ 'ļ' => 'Ļ',
+ 'ľ' => 'Ľ',
+ 'ŀ' => 'Ŀ',
+ 'ł' => 'Ł',
+ 'ń' => 'Ń',
+ 'ņ' => 'Ņ',
+ 'ň' => 'Ň',
+ 'ŋ' => 'Ŋ',
+ 'ō' => 'Ō',
+ 'ŏ' => 'Ŏ',
+ 'ő' => 'Ő',
+ 'œ' => 'Œ',
+ 'ŕ' => 'Ŕ',
+ 'ŗ' => 'Ŗ',
+ 'ř' => 'Ř',
+ 'ś' => 'Ś',
+ 'ŝ' => 'Ŝ',
+ 'ş' => 'Ş',
+ 'š' => 'Š',
+ 'ţ' => 'Ţ',
+ 'ť' => 'Ť',
+ 'ŧ' => 'Ŧ',
+ 'ũ' => 'Ũ',
+ 'ū' => 'Ū',
+ 'ŭ' => 'Ŭ',
+ 'ů' => 'Ů',
+ 'ű' => 'Ű',
+ 'ų' => 'Ų',
+ 'ŵ' => 'Ŵ',
+ 'ŷ' => 'Ŷ',
+ 'ź' => 'Ź',
+ 'ż' => 'Ż',
+ 'ž' => 'Ž',
+ 'ſ' => 'S',
+ 'ƀ' => 'Ƀ',
+ 'ƃ' => 'Ƃ',
+ 'ƅ' => 'Ƅ',
+ 'ƈ' => 'Ƈ',
+ 'ƌ' => 'Ƌ',
+ 'ƒ' => 'Ƒ',
+ 'ƕ' => 'Ƕ',
+ 'ƙ' => 'Ƙ',
+ 'ƚ' => 'Ƚ',
+ 'ƞ' => 'Ƞ',
+ 'ơ' => 'Ơ',
+ 'ƣ' => 'Ƣ',
+ 'ƥ' => 'Ƥ',
+ 'ƨ' => 'Ƨ',
+ 'ƭ' => 'Ƭ',
+ 'ư' => 'Ư',
+ 'ƴ' => 'Ƴ',
+ 'ƶ' => 'Ƶ',
+ 'ƹ' => 'Ƹ',
+ 'ƽ' => 'Ƽ',
+ 'ƿ' => 'Ƿ',
+ 'Dž' => 'DŽ',
+ 'dž' => 'DŽ',
+ 'Lj' => 'LJ',
+ 'lj' => 'LJ',
+ 'Nj' => 'NJ',
+ 'nj' => 'NJ',
+ 'ǎ' => 'Ǎ',
+ 'ǐ' => 'Ǐ',
+ 'ǒ' => 'Ǒ',
+ 'ǔ' => 'Ǔ',
+ 'ǖ' => 'Ǖ',
+ 'ǘ' => 'Ǘ',
+ 'ǚ' => 'Ǚ',
+ 'ǜ' => 'Ǜ',
+ 'ǝ' => 'Ǝ',
+ 'ǟ' => 'Ǟ',
+ 'ǡ' => 'Ǡ',
+ 'ǣ' => 'Ǣ',
+ 'ǥ' => 'Ǥ',
+ 'ǧ' => 'Ǧ',
+ 'ǩ' => 'Ǩ',
+ 'ǫ' => 'Ǫ',
+ 'ǭ' => 'Ǭ',
+ 'ǯ' => 'Ǯ',
+ 'Dz' => 'DZ',
+ 'dz' => 'DZ',
+ 'ǵ' => 'Ǵ',
+ 'ǹ' => 'Ǹ',
+ 'ǻ' => 'Ǻ',
+ 'ǽ' => 'Ǽ',
+ 'ǿ' => 'Ǿ',
+ 'ȁ' => 'Ȁ',
+ 'ȃ' => 'Ȃ',
+ 'ȅ' => 'Ȅ',
+ 'ȇ' => 'Ȇ',
+ 'ȉ' => 'Ȉ',
+ 'ȋ' => 'Ȋ',
+ 'ȍ' => 'Ȍ',
+ 'ȏ' => 'Ȏ',
+ 'ȑ' => 'Ȑ',
+ 'ȓ' => 'Ȓ',
+ 'ȕ' => 'Ȕ',
+ 'ȗ' => 'Ȗ',
+ 'ș' => 'Ș',
+ 'ț' => 'Ț',
+ 'ȝ' => 'Ȝ',
+ 'ȟ' => 'Ȟ',
+ 'ȣ' => 'Ȣ',
+ 'ȥ' => 'Ȥ',
+ 'ȧ' => 'Ȧ',
+ 'ȩ' => 'Ȩ',
+ 'ȫ' => 'Ȫ',
+ 'ȭ' => 'Ȭ',
+ 'ȯ' => 'Ȯ',
+ 'ȱ' => 'Ȱ',
+ 'ȳ' => 'Ȳ',
+ 'ȼ' => 'Ȼ',
+ 'ȿ' => 'Ȿ',
+ 'ɀ' => 'Ɀ',
+ 'ɂ' => 'Ɂ',
+ 'ɇ' => 'Ɇ',
+ 'ɉ' => 'Ɉ',
+ 'ɋ' => 'Ɋ',
+ 'ɍ' => 'Ɍ',
+ 'ɏ' => 'Ɏ',
+ 'ɐ' => 'Ɐ',
+ 'ɑ' => 'Ɑ',
+ 'ɒ' => 'Ɒ',
+ 'ɓ' => 'Ɓ',
+ 'ɔ' => 'Ɔ',
+ 'ɖ' => 'Ɖ',
+ 'ɗ' => 'Ɗ',
+ 'ə' => 'Ə',
+ 'ɛ' => 'Ɛ',
+ 'ɜ' => 'Ɜ',
+ 'ɠ' => 'Ɠ',
+ 'ɡ' => 'Ɡ',
+ 'ɣ' => 'Ɣ',
+ 'ɥ' => 'Ɥ',
+ 'ɦ' => 'Ɦ',
+ 'ɨ' => 'Ɨ',
+ 'ɩ' => 'Ɩ',
+ 'ɪ' => 'Ɪ',
+ 'ɫ' => 'Ɫ',
+ 'ɬ' => 'Ɬ',
+ 'ɯ' => 'Ɯ',
+ 'ɱ' => 'Ɱ',
+ 'ɲ' => 'Ɲ',
+ 'ɵ' => 'Ɵ',
+ 'ɽ' => 'Ɽ',
+ 'ʀ' => 'Ʀ',
+ 'ʂ' => 'Ʂ',
+ 'ʃ' => 'Ʃ',
+ 'ʇ' => 'Ʇ',
+ 'ʈ' => 'Ʈ',
+ 'ʉ' => 'Ʉ',
+ 'ʊ' => 'Ʊ',
+ 'ʋ' => 'Ʋ',
+ 'ʌ' => 'Ʌ',
+ 'ʒ' => 'Ʒ',
+ 'ʝ' => 'Ʝ',
+ 'ʞ' => 'Ʞ',
+ 'ͅ' => 'Ι',
+ 'ͱ' => 'Ͱ',
+ 'ͳ' => 'Ͳ',
+ 'ͷ' => 'Ͷ',
+ 'ͻ' => 'Ͻ',
+ 'ͼ' => 'Ͼ',
+ 'ͽ' => 'Ͽ',
+ 'ά' => 'Ά',
+ 'έ' => 'Έ',
+ 'ή' => 'Ή',
+ 'ί' => 'Ί',
+ 'α' => 'Α',
+ 'β' => 'Β',
+ 'γ' => 'Γ',
+ 'δ' => 'Δ',
+ 'ε' => 'Ε',
+ 'ζ' => 'Ζ',
+ 'η' => 'Η',
+ 'θ' => 'Θ',
+ 'ι' => 'Ι',
+ 'κ' => 'Κ',
+ 'λ' => 'Λ',
+ 'μ' => 'Μ',
+ 'ν' => 'Ν',
+ 'ξ' => 'Ξ',
+ 'ο' => 'Ο',
+ 'π' => 'Π',
+ 'ρ' => 'Ρ',
+ 'ς' => 'Σ',
+ 'σ' => 'Σ',
+ 'τ' => 'Τ',
+ 'υ' => 'Υ',
+ 'φ' => 'Φ',
+ 'χ' => 'Χ',
+ 'ψ' => 'Ψ',
+ 'ω' => 'Ω',
+ 'ϊ' => 'Ϊ',
+ 'ϋ' => 'Ϋ',
+ 'ό' => 'Ό',
+ 'ύ' => 'Ύ',
+ 'ώ' => 'Ώ',
+ 'ϐ' => 'Β',
+ 'ϑ' => 'Θ',
+ 'ϕ' => 'Φ',
+ 'ϖ' => 'Π',
+ 'ϗ' => 'Ϗ',
+ 'ϙ' => 'Ϙ',
+ 'ϛ' => 'Ϛ',
+ 'ϝ' => 'Ϝ',
+ 'ϟ' => 'Ϟ',
+ 'ϡ' => 'Ϡ',
+ 'ϣ' => 'Ϣ',
+ 'ϥ' => 'Ϥ',
+ 'ϧ' => 'Ϧ',
+ 'ϩ' => 'Ϩ',
+ 'ϫ' => 'Ϫ',
+ 'ϭ' => 'Ϭ',
+ 'ϯ' => 'Ϯ',
+ 'ϰ' => 'Κ',
+ 'ϱ' => 'Ρ',
+ 'ϲ' => 'Ϲ',
+ 'ϳ' => 'Ϳ',
+ 'ϵ' => 'Ε',
+ 'ϸ' => 'Ϸ',
+ 'ϻ' => 'Ϻ',
+ 'а' => 'А',
+ 'б' => 'Б',
+ 'в' => 'В',
+ 'г' => 'Г',
+ 'д' => 'Д',
+ 'е' => 'Е',
+ 'ж' => 'Ж',
+ 'з' => 'З',
+ 'и' => 'И',
+ 'й' => 'Й',
+ 'к' => 'К',
+ 'л' => 'Л',
+ 'м' => 'М',
+ 'н' => 'Н',
+ 'о' => 'О',
+ 'п' => 'П',
+ 'р' => 'Р',
+ 'с' => 'С',
+ 'т' => 'Т',
+ 'у' => 'У',
+ 'ф' => 'Ф',
+ 'х' => 'Х',
+ 'ц' => 'Ц',
+ 'ч' => 'Ч',
+ 'ш' => 'Ш',
+ 'щ' => 'Щ',
+ 'ъ' => 'Ъ',
+ 'ы' => 'Ы',
+ 'ь' => 'Ь',
+ 'э' => 'Э',
+ 'ю' => 'Ю',
+ 'я' => 'Я',
+ 'ѐ' => 'Ѐ',
+ 'ё' => 'Ё',
+ 'ђ' => 'Ђ',
+ 'ѓ' => 'Ѓ',
+ 'є' => 'Є',
+ 'ѕ' => 'Ѕ',
+ 'і' => 'І',
+ 'ї' => 'Ї',
+ 'ј' => 'Ј',
+ 'љ' => 'Љ',
+ 'њ' => 'Њ',
+ 'ћ' => 'Ћ',
+ 'ќ' => 'Ќ',
+ 'ѝ' => 'Ѝ',
+ 'ў' => 'Ў',
+ 'џ' => 'Џ',
+ 'ѡ' => 'Ѡ',
+ 'ѣ' => 'Ѣ',
+ 'ѥ' => 'Ѥ',
+ 'ѧ' => 'Ѧ',
+ 'ѩ' => 'Ѩ',
+ 'ѫ' => 'Ѫ',
+ 'ѭ' => 'Ѭ',
+ 'ѯ' => 'Ѯ',
+ 'ѱ' => 'Ѱ',
+ 'ѳ' => 'Ѳ',
+ 'ѵ' => 'Ѵ',
+ 'ѷ' => 'Ѷ',
+ 'ѹ' => 'Ѹ',
+ 'ѻ' => 'Ѻ',
+ 'ѽ' => 'Ѽ',
+ 'ѿ' => 'Ѿ',
+ 'ҁ' => 'Ҁ',
+ 'ҋ' => 'Ҋ',
+ 'ҍ' => 'Ҍ',
+ 'ҏ' => 'Ҏ',
+ 'ґ' => 'Ґ',
+ 'ғ' => 'Ғ',
+ 'ҕ' => 'Ҕ',
+ 'җ' => 'Җ',
+ 'ҙ' => 'Ҙ',
+ 'қ' => 'Қ',
+ 'ҝ' => 'Ҝ',
+ 'ҟ' => 'Ҟ',
+ 'ҡ' => 'Ҡ',
+ 'ң' => 'Ң',
+ 'ҥ' => 'Ҥ',
+ 'ҧ' => 'Ҧ',
+ 'ҩ' => 'Ҩ',
+ 'ҫ' => 'Ҫ',
+ 'ҭ' => 'Ҭ',
+ 'ү' => 'Ү',
+ 'ұ' => 'Ұ',
+ 'ҳ' => 'Ҳ',
+ 'ҵ' => 'Ҵ',
+ 'ҷ' => 'Ҷ',
+ 'ҹ' => 'Ҹ',
+ 'һ' => 'Һ',
+ 'ҽ' => 'Ҽ',
+ 'ҿ' => 'Ҿ',
+ 'ӂ' => 'Ӂ',
+ 'ӄ' => 'Ӄ',
+ 'ӆ' => 'Ӆ',
+ 'ӈ' => 'Ӈ',
+ 'ӊ' => 'Ӊ',
+ 'ӌ' => 'Ӌ',
+ 'ӎ' => 'Ӎ',
+ 'ӏ' => 'Ӏ',
+ 'ӑ' => 'Ӑ',
+ 'ӓ' => 'Ӓ',
+ 'ӕ' => 'Ӕ',
+ 'ӗ' => 'Ӗ',
+ 'ә' => 'Ә',
+ 'ӛ' => 'Ӛ',
+ 'ӝ' => 'Ӝ',
+ 'ӟ' => 'Ӟ',
+ 'ӡ' => 'Ӡ',
+ 'ӣ' => 'Ӣ',
+ 'ӥ' => 'Ӥ',
+ 'ӧ' => 'Ӧ',
+ 'ө' => 'Ө',
+ 'ӫ' => 'Ӫ',
+ 'ӭ' => 'Ӭ',
+ 'ӯ' => 'Ӯ',
+ 'ӱ' => 'Ӱ',
+ 'ӳ' => 'Ӳ',
+ 'ӵ' => 'Ӵ',
+ 'ӷ' => 'Ӷ',
+ 'ӹ' => 'Ӹ',
+ 'ӻ' => 'Ӻ',
+ 'ӽ' => 'Ӽ',
+ 'ӿ' => 'Ӿ',
+ 'ԁ' => 'Ԁ',
+ 'ԃ' => 'Ԃ',
+ 'ԅ' => 'Ԅ',
+ 'ԇ' => 'Ԇ',
+ 'ԉ' => 'Ԉ',
+ 'ԋ' => 'Ԋ',
+ 'ԍ' => 'Ԍ',
+ 'ԏ' => 'Ԏ',
+ 'ԑ' => 'Ԑ',
+ 'ԓ' => 'Ԓ',
+ 'ԕ' => 'Ԕ',
+ 'ԗ' => 'Ԗ',
+ 'ԙ' => 'Ԙ',
+ 'ԛ' => 'Ԛ',
+ 'ԝ' => 'Ԝ',
+ 'ԟ' => 'Ԟ',
+ 'ԡ' => 'Ԡ',
+ 'ԣ' => 'Ԣ',
+ 'ԥ' => 'Ԥ',
+ 'ԧ' => 'Ԧ',
+ 'ԩ' => 'Ԩ',
+ 'ԫ' => 'Ԫ',
+ 'ԭ' => 'Ԭ',
+ 'ԯ' => 'Ԯ',
+ 'ա' => 'Ա',
+ 'բ' => 'Բ',
+ 'գ' => 'Գ',
+ 'դ' => 'Դ',
+ 'ե' => 'Ե',
+ 'զ' => 'Զ',
+ 'է' => 'Է',
+ 'ը' => 'Ը',
+ 'թ' => 'Թ',
+ 'ժ' => 'Ժ',
+ 'ի' => 'Ի',
+ 'լ' => 'Լ',
+ 'խ' => 'Խ',
+ 'ծ' => 'Ծ',
+ 'կ' => 'Կ',
+ 'հ' => 'Հ',
+ 'ձ' => 'Ձ',
+ 'ղ' => 'Ղ',
+ 'ճ' => 'Ճ',
+ 'մ' => 'Մ',
+ 'յ' => 'Յ',
+ 'ն' => 'Ն',
+ 'շ' => 'Շ',
+ 'ո' => 'Ո',
+ 'չ' => 'Չ',
+ 'պ' => 'Պ',
+ 'ջ' => 'Ջ',
+ 'ռ' => 'Ռ',
+ 'ս' => 'Ս',
+ 'վ' => 'Վ',
+ 'տ' => 'Տ',
+ 'ր' => 'Ր',
+ 'ց' => 'Ց',
+ 'ւ' => 'Ւ',
+ 'փ' => 'Փ',
+ 'ք' => 'Ք',
+ 'օ' => 'Օ',
+ 'ֆ' => 'Ֆ',
+ 'ა' => 'Ა',
+ 'ბ' => 'Ბ',
+ 'გ' => 'Გ',
+ 'დ' => 'Დ',
+ 'ე' => 'Ე',
+ 'ვ' => 'Ვ',
+ 'ზ' => 'Ზ',
+ 'თ' => 'Თ',
+ 'ი' => 'Ი',
+ 'კ' => 'Კ',
+ 'ლ' => 'Ლ',
+ 'მ' => 'Მ',
+ 'ნ' => 'Ნ',
+ 'ო' => 'Ო',
+ 'პ' => 'Პ',
+ 'ჟ' => 'Ჟ',
+ 'რ' => 'Რ',
+ 'ს' => 'Ს',
+ 'ტ' => 'Ტ',
+ 'უ' => 'Უ',
+ 'ფ' => 'Ფ',
+ 'ქ' => 'Ქ',
+ 'ღ' => 'Ღ',
+ 'ყ' => 'Ყ',
+ 'შ' => 'Შ',
+ 'ჩ' => 'Ჩ',
+ 'ც' => 'Ც',
+ 'ძ' => 'Ძ',
+ 'წ' => 'Წ',
+ 'ჭ' => 'Ჭ',
+ 'ხ' => 'Ხ',
+ 'ჯ' => 'Ჯ',
+ 'ჰ' => 'Ჰ',
+ 'ჱ' => 'Ჱ',
+ 'ჲ' => 'Ჲ',
+ 'ჳ' => 'Ჳ',
+ 'ჴ' => 'Ჴ',
+ 'ჵ' => 'Ჵ',
+ 'ჶ' => 'Ჶ',
+ 'ჷ' => 'Ჷ',
+ 'ჸ' => 'Ჸ',
+ 'ჹ' => 'Ჹ',
+ 'ჺ' => 'Ჺ',
+ 'ჽ' => 'Ჽ',
+ 'ჾ' => 'Ჾ',
+ 'ჿ' => 'Ჿ',
+ 'ᏸ' => 'Ᏸ',
+ 'ᏹ' => 'Ᏹ',
+ 'ᏺ' => 'Ᏺ',
+ 'ᏻ' => 'Ᏻ',
+ 'ᏼ' => 'Ᏼ',
+ 'ᏽ' => 'Ᏽ',
+ 'ᲀ' => 'В',
+ 'ᲁ' => 'Д',
+ 'ᲂ' => 'О',
+ 'ᲃ' => 'С',
+ 'ᲄ' => 'Т',
+ 'ᲅ' => 'Т',
+ 'ᲆ' => 'Ъ',
+ 'ᲇ' => 'Ѣ',
+ 'ᲈ' => 'Ꙋ',
+ 'ᵹ' => 'Ᵹ',
+ 'ᵽ' => 'Ᵽ',
+ 'ᶎ' => 'Ᶎ',
+ 'ḁ' => 'Ḁ',
+ 'ḃ' => 'Ḃ',
+ 'ḅ' => 'Ḅ',
+ 'ḇ' => 'Ḇ',
+ 'ḉ' => 'Ḉ',
+ 'ḋ' => 'Ḋ',
+ 'ḍ' => 'Ḍ',
+ 'ḏ' => 'Ḏ',
+ 'ḑ' => 'Ḑ',
+ 'ḓ' => 'Ḓ',
+ 'ḕ' => 'Ḕ',
+ 'ḗ' => 'Ḗ',
+ 'ḙ' => 'Ḙ',
+ 'ḛ' => 'Ḛ',
+ 'ḝ' => 'Ḝ',
+ 'ḟ' => 'Ḟ',
+ 'ḡ' => 'Ḡ',
+ 'ḣ' => 'Ḣ',
+ 'ḥ' => 'Ḥ',
+ 'ḧ' => 'Ḧ',
+ 'ḩ' => 'Ḩ',
+ 'ḫ' => 'Ḫ',
+ 'ḭ' => 'Ḭ',
+ 'ḯ' => 'Ḯ',
+ 'ḱ' => 'Ḱ',
+ 'ḳ' => 'Ḳ',
+ 'ḵ' => 'Ḵ',
+ 'ḷ' => 'Ḷ',
+ 'ḹ' => 'Ḹ',
+ 'ḻ' => 'Ḻ',
+ 'ḽ' => 'Ḽ',
+ 'ḿ' => 'Ḿ',
+ 'ṁ' => 'Ṁ',
+ 'ṃ' => 'Ṃ',
+ 'ṅ' => 'Ṅ',
+ 'ṇ' => 'Ṇ',
+ 'ṉ' => 'Ṉ',
+ 'ṋ' => 'Ṋ',
+ 'ṍ' => 'Ṍ',
+ 'ṏ' => 'Ṏ',
+ 'ṑ' => 'Ṑ',
+ 'ṓ' => 'Ṓ',
+ 'ṕ' => 'Ṕ',
+ 'ṗ' => 'Ṗ',
+ 'ṙ' => 'Ṙ',
+ 'ṛ' => 'Ṛ',
+ 'ṝ' => 'Ṝ',
+ 'ṟ' => 'Ṟ',
+ 'ṡ' => 'Ṡ',
+ 'ṣ' => 'Ṣ',
+ 'ṥ' => 'Ṥ',
+ 'ṧ' => 'Ṧ',
+ 'ṩ' => 'Ṩ',
+ 'ṫ' => 'Ṫ',
+ 'ṭ' => 'Ṭ',
+ 'ṯ' => 'Ṯ',
+ 'ṱ' => 'Ṱ',
+ 'ṳ' => 'Ṳ',
+ 'ṵ' => 'Ṵ',
+ 'ṷ' => 'Ṷ',
+ 'ṹ' => 'Ṹ',
+ 'ṻ' => 'Ṻ',
+ 'ṽ' => 'Ṽ',
+ 'ṿ' => 'Ṿ',
+ 'ẁ' => 'Ẁ',
+ 'ẃ' => 'Ẃ',
+ 'ẅ' => 'Ẅ',
+ 'ẇ' => 'Ẇ',
+ 'ẉ' => 'Ẉ',
+ 'ẋ' => 'Ẋ',
+ 'ẍ' => 'Ẍ',
+ 'ẏ' => 'Ẏ',
+ 'ẑ' => 'Ẑ',
+ 'ẓ' => 'Ẓ',
+ 'ẕ' => 'Ẕ',
+ 'ẛ' => 'Ṡ',
+ 'ạ' => 'Ạ',
+ 'ả' => 'Ả',
+ 'ấ' => 'Ấ',
+ 'ầ' => 'Ầ',
+ 'ẩ' => 'Ẩ',
+ 'ẫ' => 'Ẫ',
+ 'ậ' => 'Ậ',
+ 'ắ' => 'Ắ',
+ 'ằ' => 'Ằ',
+ 'ẳ' => 'Ẳ',
+ 'ẵ' => 'Ẵ',
+ 'ặ' => 'Ặ',
+ 'ẹ' => 'Ẹ',
+ 'ẻ' => 'Ẻ',
+ 'ẽ' => 'Ẽ',
+ 'ế' => 'Ế',
+ 'ề' => 'Ề',
+ 'ể' => 'Ể',
+ 'ễ' => 'Ễ',
+ 'ệ' => 'Ệ',
+ 'ỉ' => 'Ỉ',
+ 'ị' => 'Ị',
+ 'ọ' => 'Ọ',
+ 'ỏ' => 'Ỏ',
+ 'ố' => 'Ố',
+ 'ồ' => 'Ồ',
+ 'ổ' => 'Ổ',
+ 'ỗ' => 'Ỗ',
+ 'ộ' => 'Ộ',
+ 'ớ' => 'Ớ',
+ 'ờ' => 'Ờ',
+ 'ở' => 'Ở',
+ 'ỡ' => 'Ỡ',
+ 'ợ' => 'Ợ',
+ 'ụ' => 'Ụ',
+ 'ủ' => 'Ủ',
+ 'ứ' => 'Ứ',
+ 'ừ' => 'Ừ',
+ 'ử' => 'Ử',
+ 'ữ' => 'Ữ',
+ 'ự' => 'Ự',
+ 'ỳ' => 'Ỳ',
+ 'ỵ' => 'Ỵ',
+ 'ỷ' => 'Ỷ',
+ 'ỹ' => 'Ỹ',
+ 'ỻ' => 'Ỻ',
+ 'ỽ' => 'Ỽ',
+ 'ỿ' => 'Ỿ',
+ 'ἀ' => 'Ἀ',
+ 'ἁ' => 'Ἁ',
+ 'ἂ' => 'Ἂ',
+ 'ἃ' => 'Ἃ',
+ 'ἄ' => 'Ἄ',
+ 'ἅ' => 'Ἅ',
+ 'ἆ' => 'Ἆ',
+ 'ἇ' => 'Ἇ',
+ 'ἐ' => 'Ἐ',
+ 'ἑ' => 'Ἑ',
+ 'ἒ' => 'Ἒ',
+ 'ἓ' => 'Ἓ',
+ 'ἔ' => 'Ἔ',
+ 'ἕ' => 'Ἕ',
+ 'ἠ' => 'Ἠ',
+ 'ἡ' => 'Ἡ',
+ 'ἢ' => 'Ἢ',
+ 'ἣ' => 'Ἣ',
+ 'ἤ' => 'Ἤ',
+ 'ἥ' => 'Ἥ',
+ 'ἦ' => 'Ἦ',
+ 'ἧ' => 'Ἧ',
+ 'ἰ' => 'Ἰ',
+ 'ἱ' => 'Ἱ',
+ 'ἲ' => 'Ἲ',
+ 'ἳ' => 'Ἳ',
+ 'ἴ' => 'Ἴ',
+ 'ἵ' => 'Ἵ',
+ 'ἶ' => 'Ἶ',
+ 'ἷ' => 'Ἷ',
+ 'ὀ' => 'Ὀ',
+ 'ὁ' => 'Ὁ',
+ 'ὂ' => 'Ὂ',
+ 'ὃ' => 'Ὃ',
+ 'ὄ' => 'Ὄ',
+ 'ὅ' => 'Ὅ',
+ 'ὑ' => 'Ὑ',
+ 'ὓ' => 'Ὓ',
+ 'ὕ' => 'Ὕ',
+ 'ὗ' => 'Ὗ',
+ 'ὠ' => 'Ὠ',
+ 'ὡ' => 'Ὡ',
+ 'ὢ' => 'Ὢ',
+ 'ὣ' => 'Ὣ',
+ 'ὤ' => 'Ὤ',
+ 'ὥ' => 'Ὥ',
+ 'ὦ' => 'Ὦ',
+ 'ὧ' => 'Ὧ',
+ 'ὰ' => 'Ὰ',
+ 'ά' => 'Ά',
+ 'ὲ' => 'Ὲ',
+ 'έ' => 'Έ',
+ 'ὴ' => 'Ὴ',
+ 'ή' => 'Ή',
+ 'ὶ' => 'Ὶ',
+ 'ί' => 'Ί',
+ 'ὸ' => 'Ὸ',
+ 'ό' => 'Ό',
+ 'ὺ' => 'Ὺ',
+ 'ύ' => 'Ύ',
+ 'ὼ' => 'Ὼ',
+ 'ώ' => 'Ώ',
+ 'ᾀ' => 'ἈΙ',
+ 'ᾁ' => 'ἉΙ',
+ 'ᾂ' => 'ἊΙ',
+ 'ᾃ' => 'ἋΙ',
+ 'ᾄ' => 'ἌΙ',
+ 'ᾅ' => 'ἍΙ',
+ 'ᾆ' => 'ἎΙ',
+ 'ᾇ' => 'ἏΙ',
+ 'ᾐ' => 'ἨΙ',
+ 'ᾑ' => 'ἩΙ',
+ 'ᾒ' => 'ἪΙ',
+ 'ᾓ' => 'ἫΙ',
+ 'ᾔ' => 'ἬΙ',
+ 'ᾕ' => 'ἭΙ',
+ 'ᾖ' => 'ἮΙ',
+ 'ᾗ' => 'ἯΙ',
+ 'ᾠ' => 'ὨΙ',
+ 'ᾡ' => 'ὩΙ',
+ 'ᾢ' => 'ὪΙ',
+ 'ᾣ' => 'ὫΙ',
+ 'ᾤ' => 'ὬΙ',
+ 'ᾥ' => 'ὭΙ',
+ 'ᾦ' => 'ὮΙ',
+ 'ᾧ' => 'ὯΙ',
+ 'ᾰ' => 'Ᾰ',
+ 'ᾱ' => 'Ᾱ',
+ 'ᾳ' => 'ΑΙ',
+ 'ι' => 'Ι',
+ 'ῃ' => 'ΗΙ',
+ 'ῐ' => 'Ῐ',
+ 'ῑ' => 'Ῑ',
+ 'ῠ' => 'Ῠ',
+ 'ῡ' => 'Ῡ',
+ 'ῥ' => 'Ῥ',
+ 'ῳ' => 'ΩΙ',
+ 'ⅎ' => 'Ⅎ',
+ 'ⅰ' => 'Ⅰ',
+ 'ⅱ' => 'Ⅱ',
+ 'ⅲ' => 'Ⅲ',
+ 'ⅳ' => 'Ⅳ',
+ 'ⅴ' => 'Ⅴ',
+ 'ⅵ' => 'Ⅵ',
+ 'ⅶ' => 'Ⅶ',
+ 'ⅷ' => 'Ⅷ',
+ 'ⅸ' => 'Ⅸ',
+ 'ⅹ' => 'Ⅹ',
+ 'ⅺ' => 'Ⅺ',
+ 'ⅻ' => 'Ⅻ',
+ 'ⅼ' => 'Ⅼ',
+ 'ⅽ' => 'Ⅽ',
+ 'ⅾ' => 'Ⅾ',
+ 'ⅿ' => 'Ⅿ',
+ 'ↄ' => 'Ↄ',
+ 'ⓐ' => 'Ⓐ',
+ 'ⓑ' => 'Ⓑ',
+ 'ⓒ' => 'Ⓒ',
+ 'ⓓ' => 'Ⓓ',
+ 'ⓔ' => 'Ⓔ',
+ 'ⓕ' => 'Ⓕ',
+ 'ⓖ' => 'Ⓖ',
+ 'ⓗ' => 'Ⓗ',
+ 'ⓘ' => 'Ⓘ',
+ 'ⓙ' => 'Ⓙ',
+ 'ⓚ' => 'Ⓚ',
+ 'ⓛ' => 'Ⓛ',
+ 'ⓜ' => 'Ⓜ',
+ 'ⓝ' => 'Ⓝ',
+ 'ⓞ' => 'Ⓞ',
+ 'ⓟ' => 'Ⓟ',
+ 'ⓠ' => 'Ⓠ',
+ 'ⓡ' => 'Ⓡ',
+ 'ⓢ' => 'Ⓢ',
+ 'ⓣ' => 'Ⓣ',
+ 'ⓤ' => 'Ⓤ',
+ 'ⓥ' => 'Ⓥ',
+ 'ⓦ' => 'Ⓦ',
+ 'ⓧ' => 'Ⓧ',
+ 'ⓨ' => 'Ⓨ',
+ 'ⓩ' => 'Ⓩ',
+ 'ⰰ' => 'Ⰰ',
+ 'ⰱ' => 'Ⰱ',
+ 'ⰲ' => 'Ⰲ',
+ 'ⰳ' => 'Ⰳ',
+ 'ⰴ' => 'Ⰴ',
+ 'ⰵ' => 'Ⰵ',
+ 'ⰶ' => 'Ⰶ',
+ 'ⰷ' => 'Ⰷ',
+ 'ⰸ' => 'Ⰸ',
+ 'ⰹ' => 'Ⰹ',
+ 'ⰺ' => 'Ⰺ',
+ 'ⰻ' => 'Ⰻ',
+ 'ⰼ' => 'Ⰼ',
+ 'ⰽ' => 'Ⰽ',
+ 'ⰾ' => 'Ⰾ',
+ 'ⰿ' => 'Ⰿ',
+ 'ⱀ' => 'Ⱀ',
+ 'ⱁ' => 'Ⱁ',
+ 'ⱂ' => 'Ⱂ',
+ 'ⱃ' => 'Ⱃ',
+ 'ⱄ' => 'Ⱄ',
+ 'ⱅ' => 'Ⱅ',
+ 'ⱆ' => 'Ⱆ',
+ 'ⱇ' => 'Ⱇ',
+ 'ⱈ' => 'Ⱈ',
+ 'ⱉ' => 'Ⱉ',
+ 'ⱊ' => 'Ⱊ',
+ 'ⱋ' => 'Ⱋ',
+ 'ⱌ' => 'Ⱌ',
+ 'ⱍ' => 'Ⱍ',
+ 'ⱎ' => 'Ⱎ',
+ 'ⱏ' => 'Ⱏ',
+ 'ⱐ' => 'Ⱐ',
+ 'ⱑ' => 'Ⱑ',
+ 'ⱒ' => 'Ⱒ',
+ 'ⱓ' => 'Ⱓ',
+ 'ⱔ' => 'Ⱔ',
+ 'ⱕ' => 'Ⱕ',
+ 'ⱖ' => 'Ⱖ',
+ 'ⱗ' => 'Ⱗ',
+ 'ⱘ' => 'Ⱘ',
+ 'ⱙ' => 'Ⱙ',
+ 'ⱚ' => 'Ⱚ',
+ 'ⱛ' => 'Ⱛ',
+ 'ⱜ' => 'Ⱜ',
+ 'ⱝ' => 'Ⱝ',
+ 'ⱞ' => 'Ⱞ',
+ 'ⱡ' => 'Ⱡ',
+ 'ⱥ' => 'Ⱥ',
+ 'ⱦ' => 'Ⱦ',
+ 'ⱨ' => 'Ⱨ',
+ 'ⱪ' => 'Ⱪ',
+ 'ⱬ' => 'Ⱬ',
+ 'ⱳ' => 'Ⱳ',
+ 'ⱶ' => 'Ⱶ',
+ 'ⲁ' => 'Ⲁ',
+ 'ⲃ' => 'Ⲃ',
+ 'ⲅ' => 'Ⲅ',
+ 'ⲇ' => 'Ⲇ',
+ 'ⲉ' => 'Ⲉ',
+ 'ⲋ' => 'Ⲋ',
+ 'ⲍ' => 'Ⲍ',
+ 'ⲏ' => 'Ⲏ',
+ 'ⲑ' => 'Ⲑ',
+ 'ⲓ' => 'Ⲓ',
+ 'ⲕ' => 'Ⲕ',
+ 'ⲗ' => 'Ⲗ',
+ 'ⲙ' => 'Ⲙ',
+ 'ⲛ' => 'Ⲛ',
+ 'ⲝ' => 'Ⲝ',
+ 'ⲟ' => 'Ⲟ',
+ 'ⲡ' => 'Ⲡ',
+ 'ⲣ' => 'Ⲣ',
+ 'ⲥ' => 'Ⲥ',
+ 'ⲧ' => 'Ⲧ',
+ 'ⲩ' => 'Ⲩ',
+ 'ⲫ' => 'Ⲫ',
+ 'ⲭ' => 'Ⲭ',
+ 'ⲯ' => 'Ⲯ',
+ 'ⲱ' => 'Ⲱ',
+ 'ⲳ' => 'Ⲳ',
+ 'ⲵ' => 'Ⲵ',
+ 'ⲷ' => 'Ⲷ',
+ 'ⲹ' => 'Ⲹ',
+ 'ⲻ' => 'Ⲻ',
+ 'ⲽ' => 'Ⲽ',
+ 'ⲿ' => 'Ⲿ',
+ 'ⳁ' => 'Ⳁ',
+ 'ⳃ' => 'Ⳃ',
+ 'ⳅ' => 'Ⳅ',
+ 'ⳇ' => 'Ⳇ',
+ 'ⳉ' => 'Ⳉ',
+ 'ⳋ' => 'Ⳋ',
+ 'ⳍ' => 'Ⳍ',
+ 'ⳏ' => 'Ⳏ',
+ 'ⳑ' => 'Ⳑ',
+ 'ⳓ' => 'Ⳓ',
+ 'ⳕ' => 'Ⳕ',
+ 'ⳗ' => 'Ⳗ',
+ 'ⳙ' => 'Ⳙ',
+ 'ⳛ' => 'Ⳛ',
+ 'ⳝ' => 'Ⳝ',
+ 'ⳟ' => 'Ⳟ',
+ 'ⳡ' => 'Ⳡ',
+ 'ⳣ' => 'Ⳣ',
+ 'ⳬ' => 'Ⳬ',
+ 'ⳮ' => 'Ⳮ',
+ 'ⳳ' => 'Ⳳ',
+ 'ⴀ' => 'Ⴀ',
+ 'ⴁ' => 'Ⴁ',
+ 'ⴂ' => 'Ⴂ',
+ 'ⴃ' => 'Ⴃ',
+ 'ⴄ' => 'Ⴄ',
+ 'ⴅ' => 'Ⴅ',
+ 'ⴆ' => 'Ⴆ',
+ 'ⴇ' => 'Ⴇ',
+ 'ⴈ' => 'Ⴈ',
+ 'ⴉ' => 'Ⴉ',
+ 'ⴊ' => 'Ⴊ',
+ 'ⴋ' => 'Ⴋ',
+ 'ⴌ' => 'Ⴌ',
+ 'ⴍ' => 'Ⴍ',
+ 'ⴎ' => 'Ⴎ',
+ 'ⴏ' => 'Ⴏ',
+ 'ⴐ' => 'Ⴐ',
+ 'ⴑ' => 'Ⴑ',
+ 'ⴒ' => 'Ⴒ',
+ 'ⴓ' => 'Ⴓ',
+ 'ⴔ' => 'Ⴔ',
+ 'ⴕ' => 'Ⴕ',
+ 'ⴖ' => 'Ⴖ',
+ 'ⴗ' => 'Ⴗ',
+ 'ⴘ' => 'Ⴘ',
+ 'ⴙ' => 'Ⴙ',
+ 'ⴚ' => 'Ⴚ',
+ 'ⴛ' => 'Ⴛ',
+ 'ⴜ' => 'Ⴜ',
+ 'ⴝ' => 'Ⴝ',
+ 'ⴞ' => 'Ⴞ',
+ 'ⴟ' => 'Ⴟ',
+ 'ⴠ' => 'Ⴠ',
+ 'ⴡ' => 'Ⴡ',
+ 'ⴢ' => 'Ⴢ',
+ 'ⴣ' => 'Ⴣ',
+ 'ⴤ' => 'Ⴤ',
+ 'ⴥ' => 'Ⴥ',
+ 'ⴧ' => 'Ⴧ',
+ 'ⴭ' => 'Ⴭ',
+ 'ꙁ' => 'Ꙁ',
+ 'ꙃ' => 'Ꙃ',
+ 'ꙅ' => 'Ꙅ',
+ 'ꙇ' => 'Ꙇ',
+ 'ꙉ' => 'Ꙉ',
+ 'ꙋ' => 'Ꙋ',
+ 'ꙍ' => 'Ꙍ',
+ 'ꙏ' => 'Ꙏ',
+ 'ꙑ' => 'Ꙑ',
+ 'ꙓ' => 'Ꙓ',
+ 'ꙕ' => 'Ꙕ',
+ 'ꙗ' => 'Ꙗ',
+ 'ꙙ' => 'Ꙙ',
+ 'ꙛ' => 'Ꙛ',
+ 'ꙝ' => 'Ꙝ',
+ 'ꙟ' => 'Ꙟ',
+ 'ꙡ' => 'Ꙡ',
+ 'ꙣ' => 'Ꙣ',
+ 'ꙥ' => 'Ꙥ',
+ 'ꙧ' => 'Ꙧ',
+ 'ꙩ' => 'Ꙩ',
+ 'ꙫ' => 'Ꙫ',
+ 'ꙭ' => 'Ꙭ',
+ 'ꚁ' => 'Ꚁ',
+ 'ꚃ' => 'Ꚃ',
+ 'ꚅ' => 'Ꚅ',
+ 'ꚇ' => 'Ꚇ',
+ 'ꚉ' => 'Ꚉ',
+ 'ꚋ' => 'Ꚋ',
+ 'ꚍ' => 'Ꚍ',
+ 'ꚏ' => 'Ꚏ',
+ 'ꚑ' => 'Ꚑ',
+ 'ꚓ' => 'Ꚓ',
+ 'ꚕ' => 'Ꚕ',
+ 'ꚗ' => 'Ꚗ',
+ 'ꚙ' => 'Ꚙ',
+ 'ꚛ' => 'Ꚛ',
+ 'ꜣ' => 'Ꜣ',
+ 'ꜥ' => 'Ꜥ',
+ 'ꜧ' => 'Ꜧ',
+ 'ꜩ' => 'Ꜩ',
+ 'ꜫ' => 'Ꜫ',
+ 'ꜭ' => 'Ꜭ',
+ 'ꜯ' => 'Ꜯ',
+ 'ꜳ' => 'Ꜳ',
+ 'ꜵ' => 'Ꜵ',
+ 'ꜷ' => 'Ꜷ',
+ 'ꜹ' => 'Ꜹ',
+ 'ꜻ' => 'Ꜻ',
+ 'ꜽ' => 'Ꜽ',
+ 'ꜿ' => 'Ꜿ',
+ 'ꝁ' => 'Ꝁ',
+ 'ꝃ' => 'Ꝃ',
+ 'ꝅ' => 'Ꝅ',
+ 'ꝇ' => 'Ꝇ',
+ 'ꝉ' => 'Ꝉ',
+ 'ꝋ' => 'Ꝋ',
+ 'ꝍ' => 'Ꝍ',
+ 'ꝏ' => 'Ꝏ',
+ 'ꝑ' => 'Ꝑ',
+ 'ꝓ' => 'Ꝓ',
+ 'ꝕ' => 'Ꝕ',
+ 'ꝗ' => 'Ꝗ',
+ 'ꝙ' => 'Ꝙ',
+ 'ꝛ' => 'Ꝛ',
+ 'ꝝ' => 'Ꝝ',
+ 'ꝟ' => 'Ꝟ',
+ 'ꝡ' => 'Ꝡ',
+ 'ꝣ' => 'Ꝣ',
+ 'ꝥ' => 'Ꝥ',
+ 'ꝧ' => 'Ꝧ',
+ 'ꝩ' => 'Ꝩ',
+ 'ꝫ' => 'Ꝫ',
+ 'ꝭ' => 'Ꝭ',
+ 'ꝯ' => 'Ꝯ',
+ 'ꝺ' => 'Ꝺ',
+ 'ꝼ' => 'Ꝼ',
+ 'ꝿ' => 'Ꝿ',
+ 'ꞁ' => 'Ꞁ',
+ 'ꞃ' => 'Ꞃ',
+ 'ꞅ' => 'Ꞅ',
+ 'ꞇ' => 'Ꞇ',
+ 'ꞌ' => 'Ꞌ',
+ 'ꞑ' => 'Ꞑ',
+ 'ꞓ' => 'Ꞓ',
+ 'ꞔ' => 'Ꞔ',
+ 'ꞗ' => 'Ꞗ',
+ 'ꞙ' => 'Ꞙ',
+ 'ꞛ' => 'Ꞛ',
+ 'ꞝ' => 'Ꞝ',
+ 'ꞟ' => 'Ꞟ',
+ 'ꞡ' => 'Ꞡ',
+ 'ꞣ' => 'Ꞣ',
+ 'ꞥ' => 'Ꞥ',
+ 'ꞧ' => 'Ꞧ',
+ 'ꞩ' => 'Ꞩ',
+ 'ꞵ' => 'Ꞵ',
+ 'ꞷ' => 'Ꞷ',
+ 'ꞹ' => 'Ꞹ',
+ 'ꞻ' => 'Ꞻ',
+ 'ꞽ' => 'Ꞽ',
+ 'ꞿ' => 'Ꞿ',
+ 'ꟃ' => 'Ꟃ',
+ 'ꟈ' => 'Ꟈ',
+ 'ꟊ' => 'Ꟊ',
+ 'ꟶ' => 'Ꟶ',
+ 'ꭓ' => 'Ꭓ',
+ 'ꭰ' => 'Ꭰ',
+ 'ꭱ' => 'Ꭱ',
+ 'ꭲ' => 'Ꭲ',
+ 'ꭳ' => 'Ꭳ',
+ 'ꭴ' => 'Ꭴ',
+ 'ꭵ' => 'Ꭵ',
+ 'ꭶ' => 'Ꭶ',
+ 'ꭷ' => 'Ꭷ',
+ 'ꭸ' => 'Ꭸ',
+ 'ꭹ' => 'Ꭹ',
+ 'ꭺ' => 'Ꭺ',
+ 'ꭻ' => 'Ꭻ',
+ 'ꭼ' => 'Ꭼ',
+ 'ꭽ' => 'Ꭽ',
+ 'ꭾ' => 'Ꭾ',
+ 'ꭿ' => 'Ꭿ',
+ 'ꮀ' => 'Ꮀ',
+ 'ꮁ' => 'Ꮁ',
+ 'ꮂ' => 'Ꮂ',
+ 'ꮃ' => 'Ꮃ',
+ 'ꮄ' => 'Ꮄ',
+ 'ꮅ' => 'Ꮅ',
+ 'ꮆ' => 'Ꮆ',
+ 'ꮇ' => 'Ꮇ',
+ 'ꮈ' => 'Ꮈ',
+ 'ꮉ' => 'Ꮉ',
+ 'ꮊ' => 'Ꮊ',
+ 'ꮋ' => 'Ꮋ',
+ 'ꮌ' => 'Ꮌ',
+ 'ꮍ' => 'Ꮍ',
+ 'ꮎ' => 'Ꮎ',
+ 'ꮏ' => 'Ꮏ',
+ 'ꮐ' => 'Ꮐ',
+ 'ꮑ' => 'Ꮑ',
+ 'ꮒ' => 'Ꮒ',
+ 'ꮓ' => 'Ꮓ',
+ 'ꮔ' => 'Ꮔ',
+ 'ꮕ' => 'Ꮕ',
+ 'ꮖ' => 'Ꮖ',
+ 'ꮗ' => 'Ꮗ',
+ 'ꮘ' => 'Ꮘ',
+ 'ꮙ' => 'Ꮙ',
+ 'ꮚ' => 'Ꮚ',
+ 'ꮛ' => 'Ꮛ',
+ 'ꮜ' => 'Ꮜ',
+ 'ꮝ' => 'Ꮝ',
+ 'ꮞ' => 'Ꮞ',
+ 'ꮟ' => 'Ꮟ',
+ 'ꮠ' => 'Ꮠ',
+ 'ꮡ' => 'Ꮡ',
+ 'ꮢ' => 'Ꮢ',
+ 'ꮣ' => 'Ꮣ',
+ 'ꮤ' => 'Ꮤ',
+ 'ꮥ' => 'Ꮥ',
+ 'ꮦ' => 'Ꮦ',
+ 'ꮧ' => 'Ꮧ',
+ 'ꮨ' => 'Ꮨ',
+ 'ꮩ' => 'Ꮩ',
+ 'ꮪ' => 'Ꮪ',
+ 'ꮫ' => 'Ꮫ',
+ 'ꮬ' => 'Ꮬ',
+ 'ꮭ' => 'Ꮭ',
+ 'ꮮ' => 'Ꮮ',
+ 'ꮯ' => 'Ꮯ',
+ 'ꮰ' => 'Ꮰ',
+ 'ꮱ' => 'Ꮱ',
+ 'ꮲ' => 'Ꮲ',
+ 'ꮳ' => 'Ꮳ',
+ 'ꮴ' => 'Ꮴ',
+ 'ꮵ' => 'Ꮵ',
+ 'ꮶ' => 'Ꮶ',
+ 'ꮷ' => 'Ꮷ',
+ 'ꮸ' => 'Ꮸ',
+ 'ꮹ' => 'Ꮹ',
+ 'ꮺ' => 'Ꮺ',
+ 'ꮻ' => 'Ꮻ',
+ 'ꮼ' => 'Ꮼ',
+ 'ꮽ' => 'Ꮽ',
+ 'ꮾ' => 'Ꮾ',
+ 'ꮿ' => 'Ꮿ',
+ 'a' => 'A',
+ 'b' => 'B',
+ 'c' => 'C',
+ 'd' => 'D',
+ 'e' => 'E',
+ 'f' => 'F',
+ 'g' => 'G',
+ 'h' => 'H',
+ 'i' => 'I',
+ 'j' => 'J',
+ 'k' => 'K',
+ 'l' => 'L',
+ 'm' => 'M',
+ 'n' => 'N',
+ 'o' => 'O',
+ 'p' => 'P',
+ 'q' => 'Q',
+ 'r' => 'R',
+ 's' => 'S',
+ 't' => 'T',
+ 'u' => 'U',
+ 'v' => 'V',
+ 'w' => 'W',
+ 'x' => 'X',
+ 'y' => 'Y',
+ 'z' => 'Z',
+ '𐐨' => '𐐀',
+ '𐐩' => '𐐁',
+ '𐐪' => '𐐂',
+ '𐐫' => '𐐃',
+ '𐐬' => '𐐄',
+ '𐐭' => '𐐅',
+ '𐐮' => '𐐆',
+ '𐐯' => '𐐇',
+ '𐐰' => '𐐈',
+ '𐐱' => '𐐉',
+ '𐐲' => '𐐊',
+ '𐐳' => '𐐋',
+ '𐐴' => '𐐌',
+ '𐐵' => '𐐍',
+ '𐐶' => '𐐎',
+ '𐐷' => '𐐏',
+ '𐐸' => '𐐐',
+ '𐐹' => '𐐑',
+ '𐐺' => '𐐒',
+ '𐐻' => '𐐓',
+ '𐐼' => '𐐔',
+ '𐐽' => '𐐕',
+ '𐐾' => '𐐖',
+ '𐐿' => '𐐗',
+ '𐑀' => '𐐘',
+ '𐑁' => '𐐙',
+ '𐑂' => '𐐚',
+ '𐑃' => '𐐛',
+ '𐑄' => '𐐜',
+ '𐑅' => '𐐝',
+ '𐑆' => '𐐞',
+ '𐑇' => '𐐟',
+ '𐑈' => '𐐠',
+ '𐑉' => '𐐡',
+ '𐑊' => '𐐢',
+ '𐑋' => '𐐣',
+ '𐑌' => '𐐤',
+ '𐑍' => '𐐥',
+ '𐑎' => '𐐦',
+ '𐑏' => '𐐧',
+ '𐓘' => '𐒰',
+ '𐓙' => '𐒱',
+ '𐓚' => '𐒲',
+ '𐓛' => '𐒳',
+ '𐓜' => '𐒴',
+ '𐓝' => '𐒵',
+ '𐓞' => '𐒶',
+ '𐓟' => '𐒷',
+ '𐓠' => '𐒸',
+ '𐓡' => '𐒹',
+ '𐓢' => '𐒺',
+ '𐓣' => '𐒻',
+ '𐓤' => '𐒼',
+ '𐓥' => '𐒽',
+ '𐓦' => '𐒾',
+ '𐓧' => '𐒿',
+ '𐓨' => '𐓀',
+ '𐓩' => '𐓁',
+ '𐓪' => '𐓂',
+ '𐓫' => '𐓃',
+ '𐓬' => '𐓄',
+ '𐓭' => '𐓅',
+ '𐓮' => '𐓆',
+ '𐓯' => '𐓇',
+ '𐓰' => '𐓈',
+ '𐓱' => '𐓉',
+ '𐓲' => '𐓊',
+ '𐓳' => '𐓋',
+ '𐓴' => '𐓌',
+ '𐓵' => '𐓍',
+ '𐓶' => '𐓎',
+ '𐓷' => '𐓏',
+ '𐓸' => '𐓐',
+ '𐓹' => '𐓑',
+ '𐓺' => '𐓒',
+ '𐓻' => '𐓓',
+ '𐳀' => '𐲀',
+ '𐳁' => '𐲁',
+ '𐳂' => '𐲂',
+ '𐳃' => '𐲃',
+ '𐳄' => '𐲄',
+ '𐳅' => '𐲅',
+ '𐳆' => '𐲆',
+ '𐳇' => '𐲇',
+ '𐳈' => '𐲈',
+ '𐳉' => '𐲉',
+ '𐳊' => '𐲊',
+ '𐳋' => '𐲋',
+ '𐳌' => '𐲌',
+ '𐳍' => '𐲍',
+ '𐳎' => '𐲎',
+ '𐳏' => '𐲏',
+ '𐳐' => '𐲐',
+ '𐳑' => '𐲑',
+ '𐳒' => '𐲒',
+ '𐳓' => '𐲓',
+ '𐳔' => '𐲔',
+ '𐳕' => '𐲕',
+ '𐳖' => '𐲖',
+ '𐳗' => '𐲗',
+ '𐳘' => '𐲘',
+ '𐳙' => '𐲙',
+ '𐳚' => '𐲚',
+ '𐳛' => '𐲛',
+ '𐳜' => '𐲜',
+ '𐳝' => '𐲝',
+ '𐳞' => '𐲞',
+ '𐳟' => '𐲟',
+ '𐳠' => '𐲠',
+ '𐳡' => '𐲡',
+ '𐳢' => '𐲢',
+ '𐳣' => '𐲣',
+ '𐳤' => '𐲤',
+ '𐳥' => '𐲥',
+ '𐳦' => '𐲦',
+ '𐳧' => '𐲧',
+ '𐳨' => '𐲨',
+ '𐳩' => '𐲩',
+ '𐳪' => '𐲪',
+ '𐳫' => '𐲫',
+ '𐳬' => '𐲬',
+ '𐳭' => '𐲭',
+ '𐳮' => '𐲮',
+ '𐳯' => '𐲯',
+ '𐳰' => '𐲰',
+ '𐳱' => '𐲱',
+ '𐳲' => '𐲲',
+ '𑣀' => '𑢠',
+ '𑣁' => '𑢡',
+ '𑣂' => '𑢢',
+ '𑣃' => '𑢣',
+ '𑣄' => '𑢤',
+ '𑣅' => '𑢥',
+ '𑣆' => '𑢦',
+ '𑣇' => '𑢧',
+ '𑣈' => '𑢨',
+ '𑣉' => '𑢩',
+ '𑣊' => '𑢪',
+ '𑣋' => '𑢫',
+ '𑣌' => '𑢬',
+ '𑣍' => '𑢭',
+ '𑣎' => '𑢮',
+ '𑣏' => '𑢯',
+ '𑣐' => '𑢰',
+ '𑣑' => '𑢱',
+ '𑣒' => '𑢲',
+ '𑣓' => '𑢳',
+ '𑣔' => '𑢴',
+ '𑣕' => '𑢵',
+ '𑣖' => '𑢶',
+ '𑣗' => '𑢷',
+ '𑣘' => '𑢸',
+ '𑣙' => '𑢹',
+ '𑣚' => '𑢺',
+ '𑣛' => '𑢻',
+ '𑣜' => '𑢼',
+ '𑣝' => '𑢽',
+ '𑣞' => '𑢾',
+ '𑣟' => '𑢿',
+ '𖹠' => '𖹀',
+ '𖹡' => '𖹁',
+ '𖹢' => '𖹂',
+ '𖹣' => '𖹃',
+ '𖹤' => '𖹄',
+ '𖹥' => '𖹅',
+ '𖹦' => '𖹆',
+ '𖹧' => '𖹇',
+ '𖹨' => '𖹈',
+ '𖹩' => '𖹉',
+ '𖹪' => '𖹊',
+ '𖹫' => '𖹋',
+ '𖹬' => '𖹌',
+ '𖹭' => '𖹍',
+ '𖹮' => '𖹎',
+ '𖹯' => '𖹏',
+ '𖹰' => '𖹐',
+ '𖹱' => '𖹑',
+ '𖹲' => '𖹒',
+ '𖹳' => '𖹓',
+ '𖹴' => '𖹔',
+ '𖹵' => '𖹕',
+ '𖹶' => '𖹖',
+ '𖹷' => '𖹗',
+ '𖹸' => '𖹘',
+ '𖹹' => '𖹙',
+ '𖹺' => '𖹚',
+ '𖹻' => '𖹛',
+ '𖹼' => '𖹜',
+ '𖹽' => '𖹝',
+ '𖹾' => '𖹞',
+ '𖹿' => '𖹟',
+ '𞤢' => '𞤀',
+ '𞤣' => '𞤁',
+ '𞤤' => '𞤂',
+ '𞤥' => '𞤃',
+ '𞤦' => '𞤄',
+ '𞤧' => '𞤅',
+ '𞤨' => '𞤆',
+ '𞤩' => '𞤇',
+ '𞤪' => '𞤈',
+ '𞤫' => '𞤉',
+ '𞤬' => '𞤊',
+ '𞤭' => '𞤋',
+ '𞤮' => '𞤌',
+ '𞤯' => '𞤍',
+ '𞤰' => '𞤎',
+ '𞤱' => '𞤏',
+ '𞤲' => '𞤐',
+ '𞤳' => '𞤑',
+ '𞤴' => '𞤒',
+ '𞤵' => '𞤓',
+ '𞤶' => '𞤔',
+ '𞤷' => '𞤕',
+ '𞤸' => '𞤖',
+ '𞤹' => '𞤗',
+ '𞤺' => '𞤘',
+ '𞤻' => '𞤙',
+ '𞤼' => '𞤚',
+ '𞤽' => '𞤛',
+ '𞤾' => '𞤜',
+ '𞤿' => '𞤝',
+ '𞥀' => '𞤞',
+ '𞥁' => '𞤟',
+ '𞥂' => '𞤠',
+ '𞥃' => '𞤡',
+ 'ß' => 'SS',
+ 'ff' => 'FF',
+ 'fi' => 'FI',
+ 'fl' => 'FL',
+ 'ffi' => 'FFI',
+ 'ffl' => 'FFL',
+ 'ſt' => 'ST',
+ 'st' => 'ST',
+ 'և' => 'ԵՒ',
+ 'ﬓ' => 'ՄՆ',
+ 'ﬔ' => 'ՄԵ',
+ 'ﬕ' => 'ՄԻ',
+ 'ﬖ' => 'ՎՆ',
+ 'ﬗ' => 'ՄԽ',
+ 'ʼn' => 'ʼN',
+ 'ΐ' => 'Ϊ́',
+ 'ΰ' => 'Ϋ́',
+ 'ǰ' => 'J̌',
+ 'ẖ' => 'H̱',
+ 'ẗ' => 'T̈',
+ 'ẘ' => 'W̊',
+ 'ẙ' => 'Y̊',
+ 'ẚ' => 'Aʾ',
+ 'ὐ' => 'Υ̓',
+ 'ὒ' => 'Υ̓̀',
+ 'ὔ' => 'Υ̓́',
+ 'ὖ' => 'Υ̓͂',
+ 'ᾶ' => 'Α͂',
+ 'ῆ' => 'Η͂',
+ 'ῒ' => 'Ϊ̀',
+ 'ΐ' => 'Ϊ́',
+ 'ῖ' => 'Ι͂',
+ 'ῗ' => 'Ϊ͂',
+ 'ῢ' => 'Ϋ̀',
+ 'ΰ' => 'Ϋ́',
+ 'ῤ' => 'Ρ̓',
+ 'ῦ' => 'Υ͂',
+ 'ῧ' => 'Ϋ͂',
+ 'ῶ' => 'Ω͂',
+ 'ᾈ' => 'ἈΙ',
+ 'ᾉ' => 'ἉΙ',
+ 'ᾊ' => 'ἊΙ',
+ 'ᾋ' => 'ἋΙ',
+ 'ᾌ' => 'ἌΙ',
+ 'ᾍ' => 'ἍΙ',
+ 'ᾎ' => 'ἎΙ',
+ 'ᾏ' => 'ἏΙ',
+ 'ᾘ' => 'ἨΙ',
+ 'ᾙ' => 'ἩΙ',
+ 'ᾚ' => 'ἪΙ',
+ 'ᾛ' => 'ἫΙ',
+ 'ᾜ' => 'ἬΙ',
+ 'ᾝ' => 'ἭΙ',
+ 'ᾞ' => 'ἮΙ',
+ 'ᾟ' => 'ἯΙ',
+ 'ᾨ' => 'ὨΙ',
+ 'ᾩ' => 'ὩΙ',
+ 'ᾪ' => 'ὪΙ',
+ 'ᾫ' => 'ὫΙ',
+ 'ᾬ' => 'ὬΙ',
+ 'ᾭ' => 'ὭΙ',
+ 'ᾮ' => 'ὮΙ',
+ 'ᾯ' => 'ὯΙ',
+ 'ᾼ' => 'ΑΙ',
+ 'ῌ' => 'ΗΙ',
+ 'ῼ' => 'ΩΙ',
+ 'ᾲ' => 'ᾺΙ',
+ 'ᾴ' => 'ΆΙ',
+ 'ῂ' => 'ῊΙ',
+ 'ῄ' => 'ΉΙ',
+ 'ῲ' => 'ῺΙ',
+ 'ῴ' => 'ΏΙ',
+ 'ᾷ' => 'Α͂Ι',
+ 'ῇ' => 'Η͂Ι',
+ 'ῷ' => 'Ω͂Ι',
+);
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/bootstrap.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/bootstrap.php
new file mode 100644
index 0000000..1fedd1f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/bootstrap.php
@@ -0,0 +1,147 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Mbstring as p;
+
+if (\PHP_VERSION_ID >= 80000) {
+ return require __DIR__.'/bootstrap80.php';
+}
+
+if (!function_exists('mb_convert_encoding')) {
+ function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); }
+}
+if (!function_exists('mb_decode_mimeheader')) {
+ function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); }
+}
+if (!function_exists('mb_encode_mimeheader')) {
+ function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); }
+}
+if (!function_exists('mb_decode_numericentity')) {
+ function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); }
+}
+if (!function_exists('mb_encode_numericentity')) {
+ function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); }
+}
+if (!function_exists('mb_convert_case')) {
+ function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); }
+}
+if (!function_exists('mb_internal_encoding')) {
+ function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); }
+}
+if (!function_exists('mb_language')) {
+ function mb_language($language = null) { return p\Mbstring::mb_language($language); }
+}
+if (!function_exists('mb_list_encodings')) {
+ function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
+}
+if (!function_exists('mb_encoding_aliases')) {
+ function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
+}
+if (!function_exists('mb_check_encoding')) {
+ function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); }
+}
+if (!function_exists('mb_detect_encoding')) {
+ function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); }
+}
+if (!function_exists('mb_detect_order')) {
+ function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); }
+}
+if (!function_exists('mb_parse_str')) {
+ function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; }
+}
+if (!function_exists('mb_strlen')) {
+ function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); }
+}
+if (!function_exists('mb_strpos')) {
+ function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); }
+}
+if (!function_exists('mb_strtolower')) {
+ function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); }
+}
+if (!function_exists('mb_strtoupper')) {
+ function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); }
+}
+if (!function_exists('mb_substitute_character')) {
+ function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); }
+}
+if (!function_exists('mb_substr')) {
+ function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); }
+}
+if (!function_exists('mb_stripos')) {
+ function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); }
+}
+if (!function_exists('mb_stristr')) {
+ function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); }
+}
+if (!function_exists('mb_strrchr')) {
+ function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); }
+}
+if (!function_exists('mb_strrichr')) {
+ function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); }
+}
+if (!function_exists('mb_strripos')) {
+ function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); }
+}
+if (!function_exists('mb_strrpos')) {
+ function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); }
+}
+if (!function_exists('mb_strstr')) {
+ function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); }
+}
+if (!function_exists('mb_get_info')) {
+ function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
+}
+if (!function_exists('mb_http_output')) {
+ function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); }
+}
+if (!function_exists('mb_strwidth')) {
+ function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); }
+}
+if (!function_exists('mb_substr_count')) {
+ function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); }
+}
+if (!function_exists('mb_output_handler')) {
+ function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); }
+}
+if (!function_exists('mb_http_input')) {
+ function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); }
+}
+
+if (!function_exists('mb_convert_variables')) {
+ function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); }
+}
+
+if (!function_exists('mb_ord')) {
+ function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); }
+}
+if (!function_exists('mb_chr')) {
+ function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); }
+}
+if (!function_exists('mb_scrub')) {
+ function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); }
+}
+if (!function_exists('mb_str_split')) {
+ function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); }
+}
+
+if (extension_loaded('mbstring')) {
+ return;
+}
+
+if (!defined('MB_CASE_UPPER')) {
+ define('MB_CASE_UPPER', 0);
+}
+if (!defined('MB_CASE_LOWER')) {
+ define('MB_CASE_LOWER', 1);
+}
+if (!defined('MB_CASE_TITLE')) {
+ define('MB_CASE_TITLE', 2);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/bootstrap80.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/bootstrap80.php
new file mode 100644
index 0000000..82f5ac4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/bootstrap80.php
@@ -0,0 +1,143 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Mbstring as p;
+
+if (!function_exists('mb_convert_encoding')) {
+ function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); }
+}
+if (!function_exists('mb_decode_mimeheader')) {
+ function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); }
+}
+if (!function_exists('mb_encode_mimeheader')) {
+ function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); }
+}
+if (!function_exists('mb_decode_numericentity')) {
+ function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); }
+}
+if (!function_exists('mb_encode_numericentity')) {
+ function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); }
+}
+if (!function_exists('mb_convert_case')) {
+ function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); }
+}
+if (!function_exists('mb_internal_encoding')) {
+ function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); }
+}
+if (!function_exists('mb_language')) {
+ function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); }
+}
+if (!function_exists('mb_list_encodings')) {
+ function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); }
+}
+if (!function_exists('mb_encoding_aliases')) {
+ function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); }
+}
+if (!function_exists('mb_check_encoding')) {
+ function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); }
+}
+if (!function_exists('mb_detect_encoding')) {
+ function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); }
+}
+if (!function_exists('mb_detect_order')) {
+ function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); }
+}
+if (!function_exists('mb_parse_str')) {
+ function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; }
+}
+if (!function_exists('mb_strlen')) {
+ function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); }
+}
+if (!function_exists('mb_strpos')) {
+ function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
+}
+if (!function_exists('mb_strtolower')) {
+ function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); }
+}
+if (!function_exists('mb_strtoupper')) {
+ function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); }
+}
+if (!function_exists('mb_substitute_character')) {
+ function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); }
+}
+if (!function_exists('mb_substr')) {
+ function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); }
+}
+if (!function_exists('mb_stripos')) {
+ function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
+}
+if (!function_exists('mb_stristr')) {
+ function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
+}
+if (!function_exists('mb_strrchr')) {
+ function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
+}
+if (!function_exists('mb_strrichr')) {
+ function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
+}
+if (!function_exists('mb_strripos')) {
+ function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
+}
+if (!function_exists('mb_strrpos')) {
+ function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
+}
+if (!function_exists('mb_strstr')) {
+ function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
+}
+if (!function_exists('mb_get_info')) {
+ function mb_get_info(?string $type = 'all'): array|string|int|false { return p\Mbstring::mb_get_info((string) $type); }
+}
+if (!function_exists('mb_http_output')) {
+ function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); }
+}
+if (!function_exists('mb_strwidth')) {
+ function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); }
+}
+if (!function_exists('mb_substr_count')) {
+ function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); }
+}
+if (!function_exists('mb_output_handler')) {
+ function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); }
+}
+if (!function_exists('mb_http_input')) {
+ function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); }
+}
+
+if (!function_exists('mb_convert_variables')) {
+ function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); }
+}
+
+if (!function_exists('mb_ord')) {
+ function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); }
+}
+if (!function_exists('mb_chr')) {
+ function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); }
+}
+if (!function_exists('mb_scrub')) {
+ function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); }
+}
+if (!function_exists('mb_str_split')) {
+ function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); }
+}
+
+if (extension_loaded('mbstring')) {
+ return;
+}
+
+if (!defined('MB_CASE_UPPER')) {
+ define('MB_CASE_UPPER', 0);
+}
+if (!defined('MB_CASE_LOWER')) {
+ define('MB_CASE_LOWER', 1);
+}
+if (!defined('MB_CASE_TITLE')) {
+ define('MB_CASE_TITLE', 2);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/composer.json
new file mode 100644
index 0000000..2ed7a74
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-mbstring/composer.json
@@ -0,0 +1,38 @@
+{
+ "name": "symfony/polyfill-mbstring",
+ "type": "library",
+ "description": "Symfony polyfill for the Mbstring extension",
+ "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.1"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" },
+ "files": [ "bootstrap.php" ]
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.23-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/LICENSE
new file mode 100644
index 0000000..5593b1d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2020 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Php80.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Php80.php
new file mode 100644
index 0000000..5fef511
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Php80.php
@@ -0,0 +1,105 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Php80;
+
+/**
+ * @author Ion Bazan <ion.bazan@gmail.com>
+ * @author Nico Oelgart <nicoswd@gmail.com>
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @internal
+ */
+final class Php80
+{
+ public static function fdiv(float $dividend, float $divisor): float
+ {
+ return @($dividend / $divisor);
+ }
+
+ public static function get_debug_type($value): string
+ {
+ switch (true) {
+ case null === $value: return 'null';
+ case \is_bool($value): return 'bool';
+ case \is_string($value): return 'string';
+ case \is_array($value): return 'array';
+ case \is_int($value): return 'int';
+ case \is_float($value): return 'float';
+ case \is_object($value): break;
+ case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class';
+ default:
+ if (null === $type = @get_resource_type($value)) {
+ return 'unknown';
+ }
+
+ if ('Unknown' === $type) {
+ $type = 'closed';
+ }
+
+ return "resource ($type)";
+ }
+
+ $class = \get_class($value);
+
+ if (false === strpos($class, '@')) {
+ return $class;
+ }
+
+ return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous';
+ }
+
+ public static function get_resource_id($res): int
+ {
+ if (!\is_resource($res) && null === @get_resource_type($res)) {
+ throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res)));
+ }
+
+ return (int) $res;
+ }
+
+ public static function preg_last_error_msg(): string
+ {
+ switch (preg_last_error()) {
+ case \PREG_INTERNAL_ERROR:
+ return 'Internal error';
+ case \PREG_BAD_UTF8_ERROR:
+ return 'Malformed UTF-8 characters, possibly incorrectly encoded';
+ case \PREG_BAD_UTF8_OFFSET_ERROR:
+ return 'The offset did not correspond to the beginning of a valid UTF-8 code point';
+ case \PREG_BACKTRACK_LIMIT_ERROR:
+ return 'Backtrack limit exhausted';
+ case \PREG_RECURSION_LIMIT_ERROR:
+ return 'Recursion limit exhausted';
+ case \PREG_JIT_STACKLIMIT_ERROR:
+ return 'JIT stack limit exhausted';
+ case \PREG_NO_ERROR:
+ return 'No error';
+ default:
+ return 'Unknown error';
+ }
+ }
+
+ public static function str_contains(string $haystack, string $needle): bool
+ {
+ return '' === $needle || false !== strpos($haystack, $needle);
+ }
+
+ public static function str_starts_with(string $haystack, string $needle): bool
+ {
+ return 0 === strncmp($haystack, $needle, \strlen($needle));
+ }
+
+ public static function str_ends_with(string $haystack, string $needle): bool
+ {
+ return '' === $needle || ('' !== $haystack && 0 === substr_compare($haystack, $needle, -\strlen($needle)));
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/README.md
new file mode 100644
index 0000000..10b8ee4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/README.md
@@ -0,0 +1,24 @@
+Symfony Polyfill / Php80
+========================
+
+This component provides features added to PHP 8.0 core:
+
+- `Stringable` interface
+- [`fdiv`](https://php.net/fdiv)
+- `ValueError` class
+- `UnhandledMatchError` class
+- `FILTER_VALIDATE_BOOL` constant
+- [`get_debug_type`](https://php.net/get_debug_type)
+- [`preg_last_error_msg`](https://php.net/preg_last_error_msg)
+- [`str_contains`](https://php.net/str_contains)
+- [`str_starts_with`](https://php.net/str_starts_with)
+- [`str_ends_with`](https://php.net/str_ends_with)
+- [`get_resource_id`](https://php.net/get_resource_id)
+
+More information can be found in the
+[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).
+
+License
+=======
+
+This library is released under the [MIT license](LICENSE).
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php
new file mode 100644
index 0000000..7ea6d27
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php
@@ -0,0 +1,22 @@
+<?php
+
+#[Attribute(Attribute::TARGET_CLASS)]
+final class Attribute
+{
+ public const TARGET_CLASS = 1;
+ public const TARGET_FUNCTION = 2;
+ public const TARGET_METHOD = 4;
+ public const TARGET_PROPERTY = 8;
+ public const TARGET_CLASS_CONSTANT = 16;
+ public const TARGET_PARAMETER = 32;
+ public const TARGET_ALL = 63;
+ public const IS_REPEATABLE = 64;
+
+ /** @var int */
+ public $flags;
+
+ public function __construct(int $flags = self::TARGET_ALL)
+ {
+ $this->flags = $flags;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php
new file mode 100644
index 0000000..77e037c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php
@@ -0,0 +1,11 @@
+<?php
+
+if (\PHP_VERSION_ID < 80000) {
+ interface Stringable
+ {
+ /**
+ * @return string
+ */
+ public function __toString();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php
new file mode 100644
index 0000000..7fb2000
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php
@@ -0,0 +1,5 @@
+<?php
+
+class UnhandledMatchError extends Error
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php
new file mode 100644
index 0000000..99843ca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php
@@ -0,0 +1,5 @@
+<?php
+
+class ValueError extends Error
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/bootstrap.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/bootstrap.php
new file mode 100644
index 0000000..e5f7dbc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/bootstrap.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Php80 as p;
+
+if (\PHP_VERSION_ID >= 80000) {
+ return;
+}
+
+if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) {
+ define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN);
+}
+
+if (!function_exists('fdiv')) {
+ function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); }
+}
+if (!function_exists('preg_last_error_msg')) {
+ function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); }
+}
+if (!function_exists('str_contains')) {
+ function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); }
+}
+if (!function_exists('str_starts_with')) {
+ function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); }
+}
+if (!function_exists('str_ends_with')) {
+ function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); }
+}
+if (!function_exists('get_debug_type')) {
+ function get_debug_type($value): string { return p\Php80::get_debug_type($value); }
+}
+if (!function_exists('get_resource_id')) {
+ function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/composer.json
new file mode 100644
index 0000000..5fe679d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/polyfill-php80/composer.json
@@ -0,0 +1,40 @@
+{
+ "name": "symfony/polyfill-php80",
+ "type": "library",
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "keywords": ["polyfill", "shim", "compatibility", "portable"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.1"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Polyfill\\Php80\\": "" },
+ "files": [ "bootstrap.php" ],
+ "classmap": [ "Resources/stubs" ]
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.23-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/.gitignore b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/.gitignore
new file mode 100644
index 0000000..c49a5d8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/CHANGELOG.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/CHANGELOG.md
new file mode 100644
index 0000000..7932e26
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/CHANGELOG.md
@@ -0,0 +1,5 @@
+CHANGELOG
+=========
+
+The changelog is maintained for all Symfony contracts at the following URL:
+https://github.com/symfony/contracts/blob/main/CHANGELOG.md
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/LICENSE
new file mode 100644
index 0000000..2358414
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2018-2021 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/LocaleAwareInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/LocaleAwareInterface.php
new file mode 100644
index 0000000..922ec1d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/LocaleAwareInterface.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Translation;
+
+interface LocaleAwareInterface
+{
+ /**
+ * Sets the current locale.
+ *
+ * @param string $locale The locale
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
+ */
+ public function setLocale(string $locale);
+
+ /**
+ * Returns the current locale.
+ *
+ * @return string The locale
+ */
+ public function getLocale();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/README.md
new file mode 100644
index 0000000..42e5c51
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/README.md
@@ -0,0 +1,9 @@
+Symfony Translation Contracts
+=============================
+
+A set of abstractions extracted out of the Symfony components.
+
+Can be used to build on semantics that the Symfony components proved useful - and
+that already have battle tested implementations.
+
+See https://github.com/symfony/contracts/blob/main/README.md for more information.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/Test/TranslatorTest.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/Test/TranslatorTest.php
new file mode 100644
index 0000000..aac9d68
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/Test/TranslatorTest.php
@@ -0,0 +1,367 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Translation\Test;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Contracts\Translation\TranslatorInterface;
+use Symfony\Contracts\Translation\TranslatorTrait;
+
+/**
+ * Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms
+ * and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms.
+ *
+ * See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms.
+ * The mozilla code is also interesting to check for.
+ *
+ * As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199
+ *
+ * The goal to cover all languages is to far fetched so this test case is smaller.
+ *
+ * @author Clemens Tolboom clemens@build2be.nl
+ */
+class TranslatorTest extends TestCase
+{
+ public function getTranslator()
+ {
+ return new class() implements TranslatorInterface {
+ use TranslatorTrait;
+ };
+ }
+
+ /**
+ * @dataProvider getTransTests
+ */
+ public function testTrans($expected, $id, $parameters)
+ {
+ $translator = $this->getTranslator();
+
+ $this->assertEquals($expected, $translator->trans($id, $parameters));
+ }
+
+ /**
+ * @dataProvider getTransChoiceTests
+ */
+ public function testTransChoiceWithExplicitLocale($expected, $id, $number)
+ {
+ $translator = $this->getTranslator();
+ $translator->setLocale('en');
+
+ $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
+ }
+
+ /**
+ * @requires extension intl
+ *
+ * @dataProvider getTransChoiceTests
+ */
+ public function testTransChoiceWithDefaultLocale($expected, $id, $number)
+ {
+ \Locale::setDefault('en');
+
+ $translator = $this->getTranslator();
+
+ $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
+ }
+
+ public function testGetSetLocale()
+ {
+ $translator = $this->getTranslator();
+ $translator->setLocale('en');
+
+ $this->assertEquals('en', $translator->getLocale());
+ }
+
+ /**
+ * @requires extension intl
+ */
+ public function testGetLocaleReturnsDefaultLocaleIfNotSet()
+ {
+ $translator = $this->getTranslator();
+
+ \Locale::setDefault('pt_BR');
+ $this->assertEquals('pt_BR', $translator->getLocale());
+
+ \Locale::setDefault('en');
+ $this->assertEquals('en', $translator->getLocale());
+ }
+
+ public function getTransTests()
+ {
+ return [
+ ['Symfony is great!', 'Symfony is great!', []],
+ ['Symfony is awesome!', 'Symfony is %what%!', ['%what%' => 'awesome']],
+ ];
+ }
+
+ public function getTransChoiceTests()
+ {
+ return [
+ ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
+ ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1],
+ ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
+ ['There are 0 apples', 'There is 1 apple|There are %count% apples', 0],
+ ['There is 1 apple', 'There is 1 apple|There are %count% apples', 1],
+ ['There are 10 apples', 'There is 1 apple|There are %count% apples', 10],
+ // custom validation messages may be coded with a fixed value
+ ['There are 2 apples', 'There are 2 apples', 2],
+ ];
+ }
+
+ /**
+ * @dataProvider getInternal
+ */
+ public function testInterval($expected, $number, $interval)
+ {
+ $translator = $this->getTranslator();
+
+ $this->assertEquals($expected, $translator->trans($interval.' foo|[1,Inf[ bar', ['%count%' => $number]));
+ }
+
+ public function getInternal()
+ {
+ return [
+ ['foo', 3, '{1,2, 3 ,4}'],
+ ['bar', 10, '{1,2, 3 ,4}'],
+ ['bar', 3, '[1,2]'],
+ ['foo', 1, '[1,2]'],
+ ['foo', 2, '[1,2]'],
+ ['bar', 1, ']1,2['],
+ ['bar', 2, ']1,2['],
+ ['foo', log(0), '[-Inf,2['],
+ ['foo', -log(0), '[-2,+Inf]'],
+ ];
+ }
+
+ /**
+ * @dataProvider getChooseTests
+ */
+ public function testChoose($expected, $id, $number, $locale = null)
+ {
+ $translator = $this->getTranslator();
+
+ $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number], null, $locale));
+ }
+
+ public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
+ {
+ $translator = $this->getTranslator();
+
+ $this->assertEquals('There are two apples', $translator->trans('There are two apples', ['%count%' => 2]));
+ }
+
+ /**
+ * @dataProvider getNonMatchingMessages
+ */
+ public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number)
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $translator = $this->getTranslator();
+
+ $translator->trans($id, ['%count%' => $number]);
+ }
+
+ public function getNonMatchingMessages()
+ {
+ return [
+ ['{0} There are no apples|{1} There is one apple', 2],
+ ['{1} There is one apple|]1,Inf] There are %count% apples', 0],
+ ['{1} There is one apple|]2,Inf] There are %count% apples', 2],
+ ['{0} There are no apples|There is one apple', 2],
+ ];
+ }
+
+ public function getChooseTests()
+ {
+ return [
+ ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
+ ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
+ ['There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
+
+ ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1],
+
+ ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
+ ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10],
+ ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
+
+ ['There are 0 apples', 'There is one apple|There are %count% apples', 0],
+ ['There is one apple', 'There is one apple|There are %count% apples', 1],
+ ['There are 10 apples', 'There is one apple|There are %count% apples', 10],
+
+ ['There are 0 apples', 'one: There is one apple|more: There are %count% apples', 0],
+ ['There is one apple', 'one: There is one apple|more: There are %count% apples', 1],
+ ['There are 10 apples', 'one: There is one apple|more: There are %count% apples', 10],
+
+ ['There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0],
+ ['There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1],
+ ['There are 10 apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10],
+
+ ['', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0],
+ ['', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1],
+
+ // Indexed only tests which are Gettext PoFile* compatible strings.
+ ['There are 0 apples', 'There is one apple|There are %count% apples', 0],
+ ['There is one apple', 'There is one apple|There are %count% apples', 1],
+ ['There are 2 apples', 'There is one apple|There are %count% apples', 2],
+
+ // Tests for float numbers
+ ['There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7],
+ ['There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1],
+ ['There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7],
+ ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0],
+ ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0],
+ ['There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0],
+
+ // Test texts with new-lines
+ // with double-quotes and \n in id & double-quotes and actual newlines in text
+ ["This is a text with a\n new-line in it. Selector = 0.", '{0}This is a text with a
+ new-line in it. Selector = 0.|{1}This is a text with a
+ new-line in it. Selector = 1.|[1,Inf]This is a text with a
+ new-line in it. Selector > 1.', 0],
+ // with double-quotes and \n in id and single-quotes and actual newlines in text
+ ["This is a text with a\n new-line in it. Selector = 1.", '{0}This is a text with a
+ new-line in it. Selector = 0.|{1}This is a text with a
+ new-line in it. Selector = 1.|[1,Inf]This is a text with a
+ new-line in it. Selector > 1.', 1],
+ ["This is a text with a\n new-line in it. Selector > 1.", '{0}This is a text with a
+ new-line in it. Selector = 0.|{1}This is a text with a
+ new-line in it. Selector = 1.|[1,Inf]This is a text with a
+ new-line in it. Selector > 1.', 5],
+ // with double-quotes and id split accros lines
+ ['This is a text with a
+ new-line in it. Selector = 1.', '{0}This is a text with a
+ new-line in it. Selector = 0.|{1}This is a text with a
+ new-line in it. Selector = 1.|[1,Inf]This is a text with a
+ new-line in it. Selector > 1.', 1],
+ // with single-quotes and id split accros lines
+ ['This is a text with a
+ new-line in it. Selector > 1.', '{0}This is a text with a
+ new-line in it. Selector = 0.|{1}This is a text with a
+ new-line in it. Selector = 1.|[1,Inf]This is a text with a
+ new-line in it. Selector > 1.', 5],
+ // with single-quotes and \n in text
+ ['This is a text with a\nnew-line in it. Selector = 0.', '{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.', 0],
+ // with double-quotes and id split accros lines
+ ["This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1],
+ // esacape pipe
+ ['This is a text with | in it. Selector = 0.', '{0}This is a text with || in it. Selector = 0.|{1}This is a text with || in it. Selector = 1.', 0],
+ // Empty plural set (2 plural forms) from a .PO file
+ ['', '|', 1],
+ // Empty plural set (3 plural forms) from a .PO file
+ ['', '||', 1],
+
+ // Floating values
+ ['1.5 liters', '%count% liter|%count% liters', 1.5],
+ ['1.5 litre', '%count% litre|%count% litres', 1.5, 'fr'],
+
+ // Negative values
+ ['-1 degree', '%count% degree|%count% degrees', -1],
+ ['-1 degré', '%count% degré|%count% degrés', -1],
+ ['-1.5 degrees', '%count% degree|%count% degrees', -1.5],
+ ['-1.5 degré', '%count% degré|%count% degrés', -1.5, 'fr'],
+ ['-2 degrees', '%count% degree|%count% degrees', -2],
+ ['-2 degrés', '%count% degré|%count% degrés', -2],
+ ];
+ }
+
+ /**
+ * @dataProvider failingLangcodes
+ */
+ public function testFailedLangcodes($nplural, $langCodes)
+ {
+ $matrix = $this->generateTestData($langCodes);
+ $this->validateMatrix($nplural, $matrix, false);
+ }
+
+ /**
+ * @dataProvider successLangcodes
+ */
+ public function testLangcodes($nplural, $langCodes)
+ {
+ $matrix = $this->generateTestData($langCodes);
+ $this->validateMatrix($nplural, $matrix);
+ }
+
+ /**
+ * This array should contain all currently known langcodes.
+ *
+ * As it is impossible to have this ever complete we should try as hard as possible to have it almost complete.
+ *
+ * @return array
+ */
+ public function successLangcodes()
+ {
+ return [
+ ['1', ['ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky']],
+ ['2', ['nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM']],
+ ['3', ['be', 'bs', 'cs', 'hr']],
+ ['4', ['cy', 'mt', 'sl']],
+ ['6', ['ar']],
+ ];
+ }
+
+ /**
+ * This array should be at least empty within the near future.
+ *
+ * This both depends on a complete list trying to add above as understanding
+ * the plural rules of the current failing languages.
+ *
+ * @return array with nplural together with langcodes
+ */
+ public function failingLangcodes()
+ {
+ return [
+ ['1', ['fa']],
+ ['2', ['jbo']],
+ ['3', ['cbs']],
+ ['4', ['gd', 'kw']],
+ ['5', ['ga']],
+ ];
+ }
+
+ /**
+ * We validate only on the plural coverage. Thus the real rules is not tested.
+ *
+ * @param string $nplural Plural expected
+ * @param array $matrix Containing langcodes and their plural index values
+ * @param bool $expectSuccess
+ */
+ protected function validateMatrix($nplural, $matrix, $expectSuccess = true)
+ {
+ foreach ($matrix as $langCode => $data) {
+ $indexes = array_flip($data);
+ if ($expectSuccess) {
+ $this->assertEquals($nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
+ } else {
+ $this->assertNotEquals((int) $nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
+ }
+ }
+ }
+
+ protected function generateTestData($langCodes)
+ {
+ $translator = new class() {
+ use TranslatorTrait {
+ getPluralizationRule as public;
+ }
+ };
+
+ $matrix = [];
+ foreach ($langCodes as $langCode) {
+ for ($count = 0; $count < 200; ++$count) {
+ $plural = $translator->getPluralizationRule($count, $langCode);
+ $matrix[$langCode][$count] = $plural;
+ }
+ }
+
+ return $matrix;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/TranslatableInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/TranslatableInterface.php
new file mode 100644
index 0000000..47fd6fa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/TranslatableInterface.php
@@ -0,0 +1,20 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Translation;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+interface TranslatableInterface
+{
+ public function trans(TranslatorInterface $translator, string $locale = null): string;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/TranslatorInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/TranslatorInterface.php
new file mode 100644
index 0000000..dc9bf7f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/TranslatorInterface.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Translation;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @method string getLocale() Returns the default locale
+ */
+interface TranslatorInterface
+{
+ /**
+ * Translates the given message.
+ *
+ * When a number is provided as a parameter named "%count%", the message is parsed for plural
+ * forms and a translation is chosen according to this number using the following rules:
+ *
+ * Given a message with different plural translations separated by a
+ * pipe (|), this method returns the correct portion of the message based
+ * on the given number, locale and the pluralization rules in the message
+ * itself.
+ *
+ * The message supports two different types of pluralization rules:
+ *
+ * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples
+ * indexed: There is one apple|There are %count% apples
+ *
+ * The indexed solution can also contain labels (e.g. one: There is one apple).
+ * This is purely for making the translations more clear - it does not
+ * affect the functionality.
+ *
+ * The two methods can also be mixed:
+ * {0} There are no apples|one: There is one apple|more: There are %count% apples
+ *
+ * An interval can represent a finite set of numbers:
+ * {1,2,3,4}
+ *
+ * An interval can represent numbers between two numbers:
+ * [1, +Inf]
+ * ]-1,2[
+ *
+ * The left delimiter can be [ (inclusive) or ] (exclusive).
+ * The right delimiter can be [ (exclusive) or ] (inclusive).
+ * Beside numbers, you can use -Inf and +Inf for the infinite.
+ *
+ * @see https://en.wikipedia.org/wiki/ISO_31-11
+ *
+ * @param string $id The message id (may also be an object that can be cast to string)
+ * @param array $parameters An array of parameters for the message
+ * @param string|null $domain The domain for the message or null to use the default
+ * @param string|null $locale The locale or null to use the default
+ *
+ * @return string The translated string
+ *
+ * @throws \InvalidArgumentException If the locale contains invalid characters
+ */
+ public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/TranslatorTrait.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/TranslatorTrait.php
new file mode 100644
index 0000000..789693d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/TranslatorTrait.php
@@ -0,0 +1,261 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Translation;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+
+/**
+ * A trait to help implement TranslatorInterface and LocaleAwareInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+trait TranslatorTrait
+{
+ private $locale;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale(string $locale)
+ {
+ $this->locale = $locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return string
+ */
+ public function getLocale()
+ {
+ return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null): string
+ {
+ if (null === $id || '' === $id) {
+ return '';
+ }
+
+ if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) {
+ return strtr($id, $parameters);
+ }
+
+ $number = (float) $parameters['%count%'];
+ $locale = $locale ?: $this->getLocale();
+
+ $parts = [];
+ if (preg_match('/^\|++$/', $id)) {
+ $parts = explode('|', $id);
+ } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) {
+ $parts = $matches[0];
+ }
+
+ $intervalRegexp = <<<'EOF'
+/^(?P<interval>
+ ({\s*
+ (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
+ \s*})
+
+ |
+
+ (?P<left_delimiter>[\[\]])
+ \s*
+ (?P<left>-Inf|\-?\d+(\.\d+)?)
+ \s*,\s*
+ (?P<right>\+?Inf|\-?\d+(\.\d+)?)
+ \s*
+ (?P<right_delimiter>[\[\]])
+)\s*(?P<message>.*?)$/xs
+EOF;
+
+ $standardRules = [];
+ foreach ($parts as $part) {
+ $part = trim(str_replace('||', '|', $part));
+
+ // try to match an explicit rule, then fallback to the standard ones
+ if (preg_match($intervalRegexp, $part, $matches)) {
+ if ($matches[2]) {
+ foreach (explode(',', $matches[3]) as $n) {
+ if ($number == $n) {
+ return strtr($matches['message'], $parameters);
+ }
+ }
+ } else {
+ $leftNumber = '-Inf' === $matches['left'] ? -\INF : (float) $matches['left'];
+ $rightNumber = is_numeric($matches['right']) ? (float) $matches['right'] : \INF;
+
+ if (('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
+ && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
+ ) {
+ return strtr($matches['message'], $parameters);
+ }
+ }
+ } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) {
+ $standardRules[] = $matches[1];
+ } else {
+ $standardRules[] = $part;
+ }
+ }
+
+ $position = $this->getPluralizationRule($number, $locale);
+
+ if (!isset($standardRules[$position])) {
+ // when there's exactly one rule given, and that rule is a standard
+ // rule, use this rule
+ if (1 === \count($parts) && isset($standardRules[0])) {
+ return strtr($standardRules[0], $parameters);
+ }
+
+ $message = sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number);
+
+ if (class_exists(InvalidArgumentException::class)) {
+ throw new InvalidArgumentException($message);
+ }
+
+ throw new \InvalidArgumentException($message);
+ }
+
+ return strtr($standardRules[$position], $parameters);
+ }
+
+ /**
+ * Returns the plural position to use for the given locale and number.
+ *
+ * The plural rules are derived from code of the Zend Framework (2010-09-25),
+ * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
+ * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ */
+ private function getPluralizationRule(float $number, string $locale): int
+ {
+ $number = abs($number);
+
+ switch ('pt_BR' !== $locale && \strlen($locale) > 3 ? substr($locale, 0, strrpos($locale, '_')) : $locale) {
+ case 'af':
+ case 'bn':
+ case 'bg':
+ case 'ca':
+ case 'da':
+ case 'de':
+ case 'el':
+ case 'en':
+ case 'eo':
+ case 'es':
+ case 'et':
+ case 'eu':
+ case 'fa':
+ case 'fi':
+ case 'fo':
+ case 'fur':
+ case 'fy':
+ case 'gl':
+ case 'gu':
+ case 'ha':
+ case 'he':
+ case 'hu':
+ case 'is':
+ case 'it':
+ case 'ku':
+ case 'lb':
+ case 'ml':
+ case 'mn':
+ case 'mr':
+ case 'nah':
+ case 'nb':
+ case 'ne':
+ case 'nl':
+ case 'nn':
+ case 'no':
+ case 'oc':
+ case 'om':
+ case 'or':
+ case 'pa':
+ case 'pap':
+ case 'ps':
+ case 'pt':
+ case 'so':
+ case 'sq':
+ case 'sv':
+ case 'sw':
+ case 'ta':
+ case 'te':
+ case 'tk':
+ case 'ur':
+ case 'zu':
+ return (1 == $number) ? 0 : 1;
+
+ case 'am':
+ case 'bh':
+ case 'fil':
+ case 'fr':
+ case 'gun':
+ case 'hi':
+ case 'hy':
+ case 'ln':
+ case 'mg':
+ case 'nso':
+ case 'pt_BR':
+ case 'ti':
+ case 'wa':
+ return ($number < 2) ? 0 : 1;
+
+ case 'be':
+ case 'bs':
+ case 'hr':
+ case 'ru':
+ case 'sh':
+ case 'sr':
+ case 'uk':
+ return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+
+ case 'cs':
+ case 'sk':
+ return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2);
+
+ case 'ga':
+ return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2);
+
+ case 'lt':
+ return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+
+ case 'sl':
+ return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3));
+
+ case 'mk':
+ return (1 == $number % 10) ? 0 : 1;
+
+ case 'mt':
+ return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3));
+
+ case 'lv':
+ return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2);
+
+ case 'pl':
+ return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2);
+
+ case 'cy':
+ return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3));
+
+ case 'ro':
+ return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2);
+
+ case 'ar':
+ return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5))));
+
+ default:
+ return 0;
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/composer.json
new file mode 100644
index 0000000..00e27f8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation-contracts/composer.json
@@ -0,0 +1,37 @@
+{
+ "name": "symfony/translation-contracts",
+ "type": "library",
+ "description": "Generic abstractions related to translation",
+ "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.2.5"
+ },
+ "suggest": {
+ "symfony/translation-implementation": ""
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Contracts\\Translation\\": "" }
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/CHANGELOG.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/CHANGELOG.md
new file mode 100644
index 0000000..3341328
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/CHANGELOG.md
@@ -0,0 +1,169 @@
+CHANGELOG
+=========
+
+5.3
+---
+
+ * Add `translation:pull` and `translation:push` commands to manage translations with third-party providers
+ * Add `TranslatorBagInterface::getCatalogues` method
+ * Add support to load XLIFF string in `XliffFileLoader`
+
+5.2.0
+-----
+
+ * added support for calling `trans` with ICU formatted messages
+ * added `PseudoLocalizationTranslator`
+ * added `TranslatableMessage` objects that represent a message that can be translated
+ * added the `t()` function to easily create `TranslatableMessage` objects
+ * Added support for extracting messages from `TranslatableMessage` objects
+
+5.1.0
+-----
+
+ * added support for `name` attribute on `unit` element from xliff2 to be used as a translation key instead of always the `source` element
+
+5.0.0
+-----
+
+ * removed support for using `null` as the locale in `Translator`
+ * removed `TranslatorInterface`
+ * removed `MessageSelector`
+ * removed `ChoiceMessageFormatterInterface`
+ * removed `PluralizationRule`
+ * removed `Interval`
+ * removed `transChoice()` methods, use the trans() method instead with a %count% parameter
+ * removed `FileDumper::setBackup()` and `TranslationWriter::disableBackup()`
+ * removed `MessageFormatter::choiceFormat()`
+ * added argument `$filename` to `PhpExtractor::parseTokens()`
+ * removed support for implicit STDIN usage in the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit.
+
+4.4.0
+-----
+
+ * deprecated support for using `null` as the locale in `Translator`
+ * deprecated accepting STDIN implicitly when using the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit.
+ * Marked the `TranslationDataCollector` class as `@final`.
+
+4.3.0
+-----
+
+ * Improved Xliff 1.2 loader to load the original file's metadata
+ * Added `TranslatorPathsPass`
+
+4.2.0
+-----
+
+ * Started using ICU parent locales as fallback locales.
+ * allow using the ICU message format using domains with the "+intl-icu" suffix
+ * deprecated `Translator::transChoice()` in favor of using `Translator::trans()` with a `%count%` parameter
+ * deprecated `TranslatorInterface` in favor of `Symfony\Contracts\Translation\TranslatorInterface`
+ * deprecated `MessageSelector`, `Interval` and `PluralizationRules`; use `IdentityTranslator` instead
+ * Added `IntlFormatter` and `IntlFormatterInterface`
+ * added support for multiple files and directories in `XliffLintCommand`
+ * Marked `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` as internal
+
+4.1.0
+-----
+
+ * The `FileDumper::setBackup()` method is deprecated.
+ * The `TranslationWriter::disableBackup()` method is deprecated.
+ * The `XliffFileDumper` will write "name" on the "unit" node when dumping XLIFF 2.0.
+
+4.0.0
+-----
+
+ * removed the backup feature of the `FileDumper` class
+ * removed `TranslationWriter::writeTranslations()` method
+ * removed support for passing `MessageSelector` instances to the constructor of the `Translator` class
+
+3.4.0
+-----
+
+ * Added `TranslationDumperPass`
+ * Added `TranslationExtractorPass`
+ * Added `TranslatorPass`
+ * Added `TranslationReader` and `TranslationReaderInterface`
+ * Added `<notes>` section to the Xliff 2.0 dumper.
+ * Improved Xliff 2.0 loader to load `<notes>` section.
+ * Added `TranslationWriterInterface`
+ * Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write`
+ * added support for adding custom message formatter and decoupling the default one.
+ * Added `PhpExtractor`
+ * Added `PhpStringTokenParser`
+
+3.2.0
+-----
+
+ * Added support for escaping `|` in plural translations with double pipe.
+
+3.1.0
+-----
+
+ * Deprecated the backup feature of the file dumper classes.
+
+3.0.0
+-----
+
+ * removed `FileDumper::format()` method.
+ * Changed the visibility of the locale property in `Translator` from protected to private.
+
+2.8.0
+-----
+
+ * deprecated FileDumper::format(), overwrite FileDumper::formatCatalogue() instead.
+ * deprecated Translator::getMessages(), rely on TranslatorBagInterface::getCatalogue() instead.
+ * added `FileDumper::formatCatalogue` which allows format the catalogue without dumping it into file.
+ * added option `json_encoding` to JsonFileDumper
+ * added options `as_tree`, `inline` to YamlFileDumper
+ * added support for XLIFF 2.0.
+ * added support for XLIFF target and tool attributes.
+ * added message parameters to DataCollectorTranslator.
+ * [DEPRECATION] The `DiffOperation` class has been deprecated and
+ will be removed in Symfony 3.0, since its operation has nothing to do with 'diff',
+ so the class name is misleading. The `TargetOperation` class should be used for
+ this use-case instead.
+
+2.7.0
+-----
+
+ * added DataCollectorTranslator for collecting the translated messages.
+
+2.6.0
+-----
+
+ * added possibility to cache catalogues
+ * added TranslatorBagInterface
+ * added LoggingTranslator
+ * added Translator::getMessages() for retrieving the message catalogue as an array
+
+2.5.0
+-----
+
+ * added relative file path template to the file dumpers
+ * added optional backup to the file dumpers
+ * changed IcuResFileDumper to extend FileDumper
+
+2.3.0
+-----
+
+ * added classes to make operations on catalogues (like making a diff or a merge on 2 catalogues)
+ * added Translator::getFallbackLocales()
+ * deprecated Translator::setFallbackLocale() in favor of the new Translator::setFallbackLocales() method
+
+2.2.0
+-----
+
+ * QtTranslationsLoader class renamed to QtFileLoader. QtTranslationsLoader is deprecated and will be removed in 2.3.
+ * [BC BREAK] uniformized the exception thrown by the load() method when an error occurs. The load() method now
+ throws Symfony\Component\Translation\Exception\NotFoundResourceException when a resource cannot be found
+ and Symfony\Component\Translation\Exception\InvalidResourceException when a resource is invalid.
+ * changed the exception class thrown by some load() methods from \RuntimeException to \InvalidArgumentException
+ (IcuDatFileLoader, IcuResFileLoader and QtFileLoader)
+
+2.1.0
+-----
+
+ * added support for more than one fallback locale
+ * added support for extracting translation messages from templates (Twig and PHP)
+ * added dumpers for translation catalogs
+ * added support for QT, gettext, and ResourceBundles
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/AbstractOperation.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/AbstractOperation.php
new file mode 100644
index 0000000..9869fbb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/AbstractOperation.php
@@ -0,0 +1,192 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\LogicException;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * Base catalogues binary operation class.
+ *
+ * A catalogue binary operation performs operation on
+ * source (the left argument) and target (the right argument) catalogues.
+ *
+ * @author Jean-François Simon <contact@jfsimon.fr>
+ */
+abstract class AbstractOperation implements OperationInterface
+{
+ public const OBSOLETE_BATCH = 'obsolete';
+ public const NEW_BATCH = 'new';
+ public const ALL_BATCH = 'all';
+
+ protected $source;
+ protected $target;
+ protected $result;
+
+ /**
+ * @var array|null The domains affected by this operation
+ */
+ private $domains;
+
+ /**
+ * This array stores 'all', 'new' and 'obsolete' messages for all valid domains.
+ *
+ * The data structure of this array is as follows:
+ *
+ * [
+ * 'domain 1' => [
+ * 'all' => [...],
+ * 'new' => [...],
+ * 'obsolete' => [...]
+ * ],
+ * 'domain 2' => [
+ * 'all' => [...],
+ * 'new' => [...],
+ * 'obsolete' => [...]
+ * ],
+ * ...
+ * ]
+ *
+ * @var array The array that stores 'all', 'new' and 'obsolete' messages
+ */
+ protected $messages;
+
+ /**
+ * @throws LogicException
+ */
+ public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
+ {
+ if ($source->getLocale() !== $target->getLocale()) {
+ throw new LogicException('Operated catalogues must belong to the same locale.');
+ }
+
+ $this->source = $source;
+ $this->target = $target;
+ $this->result = new MessageCatalogue($source->getLocale());
+ $this->messages = [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDomains()
+ {
+ if (null === $this->domains) {
+ $this->domains = array_values(array_unique(array_merge($this->source->getDomains(), $this->target->getDomains())));
+ }
+
+ return $this->domains;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMessages(string $domain)
+ {
+ if (!\in_array($domain, $this->getDomains())) {
+ throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
+ }
+
+ if (!isset($this->messages[$domain][self::ALL_BATCH])) {
+ $this->processDomain($domain);
+ }
+
+ return $this->messages[$domain][self::ALL_BATCH];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNewMessages(string $domain)
+ {
+ if (!\in_array($domain, $this->getDomains())) {
+ throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
+ }
+
+ if (!isset($this->messages[$domain][self::NEW_BATCH])) {
+ $this->processDomain($domain);
+ }
+
+ return $this->messages[$domain][self::NEW_BATCH];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getObsoleteMessages(string $domain)
+ {
+ if (!\in_array($domain, $this->getDomains())) {
+ throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
+ }
+
+ if (!isset($this->messages[$domain][self::OBSOLETE_BATCH])) {
+ $this->processDomain($domain);
+ }
+
+ return $this->messages[$domain][self::OBSOLETE_BATCH];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getResult()
+ {
+ foreach ($this->getDomains() as $domain) {
+ if (!isset($this->messages[$domain])) {
+ $this->processDomain($domain);
+ }
+ }
+
+ return $this->result;
+ }
+
+ /**
+ * @param self::*_BATCH $batch
+ */
+ public function moveMessagesToIntlDomainsIfPossible(string $batch = self::ALL_BATCH): void
+ {
+ // If MessageFormatter class does not exists, intl domains are not supported.
+ if (!class_exists(\MessageFormatter::class)) {
+ return;
+ }
+
+ foreach ($this->getDomains() as $domain) {
+ $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
+ switch ($batch) {
+ case self::OBSOLETE_BATCH: $messages = $this->getObsoleteMessages($domain); break;
+ case self::NEW_BATCH: $messages = $this->getNewMessages($domain); break;
+ case self::ALL_BATCH: $messages = $this->getMessages($domain); break;
+ default: throw new \InvalidArgumentException(sprintf('$batch argument must be one of ["%s", "%s", "%s"].', self::ALL_BATCH, self::NEW_BATCH, self::OBSOLETE_BATCH));
+ }
+
+ if (!$messages || (!$this->source->all($intlDomain) && $this->source->all($domain))) {
+ continue;
+ }
+
+ $result = $this->getResult();
+ $allIntlMessages = $result->all($intlDomain);
+ $currentMessages = array_diff_key($messages, $result->all($domain));
+ $result->replace($currentMessages, $domain);
+ $result->replace($allIntlMessages + $messages, $intlDomain);
+ }
+ }
+
+ /**
+ * Performs operation on source and target catalogues for the given domain and
+ * stores the results.
+ *
+ * @param string $domain The domain which the operation will be performed for
+ */
+ abstract protected function processDomain(string $domain);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/MergeOperation.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/MergeOperation.php
new file mode 100644
index 0000000..87db2fb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/MergeOperation.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * Merge operation between two catalogues as follows:
+ * all = source ∪ target = {x: x ∈ source ∨ x ∈ target}
+ * new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
+ * obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ source ∧ x ∉ target} = ∅
+ * Basically, the result contains messages from both catalogues.
+ *
+ * @author Jean-François Simon <contact@jfsimon.fr>
+ */
+class MergeOperation extends AbstractOperation
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function processDomain(string $domain)
+ {
+ $this->messages[$domain] = [
+ 'all' => [],
+ 'new' => [],
+ 'obsolete' => [],
+ ];
+ $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
+
+ foreach ($this->source->all($domain) as $id => $message) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $d = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain;
+ $this->result->add([$id => $message], $d);
+ if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) {
+ $this->result->setMetadata($id, $keyMetadata, $d);
+ }
+ }
+
+ foreach ($this->target->all($domain) as $id => $message) {
+ if (!$this->source->has($id, $domain)) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $this->messages[$domain]['new'][$id] = $message;
+ $d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
+ $this->result->add([$id => $message], $d);
+ if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) {
+ $this->result->setMetadata($id, $keyMetadata, $d);
+ }
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/OperationInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/OperationInterface.php
new file mode 100644
index 0000000..9ffac88
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/OperationInterface.php
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * Represents an operation on catalogue(s).
+ *
+ * An instance of this interface performs an operation on one or more catalogues and
+ * stores intermediate and final results of the operation.
+ *
+ * The first catalogue in its argument(s) is called the 'source catalogue' or 'source' and
+ * the following results are stored:
+ *
+ * Messages: also called 'all', are valid messages for the given domain after the operation is performed.
+ *
+ * New Messages: also called 'new' (new = all ∖ source = {x: x ∈ all ∧ x ∉ source}).
+ *
+ * Obsolete Messages: also called 'obsolete' (obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ all}).
+ *
+ * Result: also called 'result', is the resulting catalogue for the given domain that holds the same messages as 'all'.
+ *
+ * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
+ */
+interface OperationInterface
+{
+ /**
+ * Returns domains affected by operation.
+ *
+ * @return array
+ */
+ public function getDomains();
+
+ /**
+ * Returns all valid messages ('all') after operation.
+ *
+ * @return array
+ */
+ public function getMessages(string $domain);
+
+ /**
+ * Returns new messages ('new') after operation.
+ *
+ * @return array
+ */
+ public function getNewMessages(string $domain);
+
+ /**
+ * Returns obsolete messages ('obsolete') after operation.
+ *
+ * @return array
+ */
+ public function getObsoleteMessages(string $domain);
+
+ /**
+ * Returns resulting catalogue ('result').
+ *
+ * @return MessageCatalogueInterface
+ */
+ public function getResult();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/TargetOperation.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/TargetOperation.php
new file mode 100644
index 0000000..399d917
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/TargetOperation.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * Target operation between two catalogues:
+ * intersection = source ∩ target = {x: x ∈ source ∧ x ∈ target}
+ * all = intersection ∪ (target ∖ intersection) = target
+ * new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
+ * obsolete = source ∖ all = source ∖ target = {x: x ∈ source ∧ x ∉ target}
+ * Basically, the result contains messages from the target catalogue.
+ *
+ * @author Michael Lee <michael.lee@zerustech.com>
+ */
+class TargetOperation extends AbstractOperation
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function processDomain(string $domain)
+ {
+ $this->messages[$domain] = [
+ 'all' => [],
+ 'new' => [],
+ 'obsolete' => [],
+ ];
+ $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
+
+ // For 'all' messages, the code can't be simplified as ``$this->messages[$domain]['all'] = $target->all($domain);``,
+ // because doing so will drop messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
+ //
+ // For 'new' messages, the code can't be simplified as ``array_diff_assoc($this->target->all($domain), $this->source->all($domain));``
+ // because doing so will not exclude messages like {x: x ∈ target ∧ x ∉ source.all ∧ x ∈ source.fallback}
+ //
+ // For 'obsolete' messages, the code can't be simplified as ``array_diff_assoc($this->source->all($domain), $this->target->all($domain))``
+ // because doing so will not exclude messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
+
+ foreach ($this->source->all($domain) as $id => $message) {
+ if ($this->target->has($id, $domain)) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
+ $this->result->add([$id => $message], $d);
+ if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) {
+ $this->result->setMetadata($id, $keyMetadata, $d);
+ }
+ } else {
+ $this->messages[$domain]['obsolete'][$id] = $message;
+ }
+ }
+
+ foreach ($this->target->all($domain) as $id => $message) {
+ if (!$this->source->has($id, $domain)) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $this->messages[$domain]['new'][$id] = $message;
+ $d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
+ $this->result->add([$id => $message], $d);
+ if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) {
+ $this->result->setMetadata($id, $keyMetadata, $d);
+ }
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPullCommand.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPullCommand.php
new file mode 100644
index 0000000..0ec02ca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPullCommand.php
@@ -0,0 +1,157 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Translation\Catalogue\TargetOperation;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Provider\TranslationProviderCollection;
+use Symfony\Component\Translation\Reader\TranslationReaderInterface;
+use Symfony\Component\Translation\Writer\TranslationWriterInterface;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+final class TranslationPullCommand extends Command
+{
+ use TranslationTrait;
+
+ protected static $defaultName = 'translation:pull';
+ protected static $defaultDescription = 'Pull translations from a given provider.';
+
+ private $providerCollection;
+ private $writer;
+ private $reader;
+ private $defaultLocale;
+ private $transPaths;
+ private $enabledLocales;
+
+ public function __construct(TranslationProviderCollection $providerCollection, TranslationWriterInterface $writer, TranslationReaderInterface $reader, string $defaultLocale, array $transPaths = [], array $enabledLocales = [])
+ {
+ $this->providerCollection = $providerCollection;
+ $this->writer = $writer;
+ $this->reader = $reader;
+ $this->defaultLocale = $defaultLocale;
+ $this->transPaths = $transPaths;
+ $this->enabledLocales = $enabledLocales;
+
+ parent::__construct();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $keys = $this->providerCollection->keys();
+ $defaultProvider = 1 === \count($keys) ? $keys[0] : null;
+
+ $this
+ ->setDefinition([
+ new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to pull translations from.', $defaultProvider),
+ new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with provider ones (it will delete not synchronized messages).'),
+ new InputOption('intl-icu', null, InputOption::VALUE_NONE, 'Associated to --force option, it will write messages in "%domain%+intl-icu.%locale%.xlf" files.'),
+ new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to pull.'),
+ new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to pull.'),
+ new InputOption('format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format.', 'xlf12'),
+ ])
+ ->setHelp(<<<'EOF'
+The <info>%command.name%</> command pulls translations from the given provider. Only
+new translations are pulled, existing ones are not overwritten.
+
+You can overwrite existing translations (and remove the missing ones on local side) by using the <comment>--force</> flag:
+
+ <info>php %command.full_name% --force provider</>
+
+Full example:
+
+ <info>php %command.full_name% provider --force --domains=messages,validators --locales=en</>
+
+This command pulls all translations associated with the <comment>messages</> and <comment>validators</> domains for the <comment>en</> locale.
+Local translations for the specified domains and locale are deleted if they're not present on the provider and overwritten if it's the case.
+Local translations for others domains and locales are ignored.
+EOF
+ )
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ $provider = $this->providerCollection->get($input->getArgument('provider'));
+ $force = $input->getOption('force');
+ $intlIcu = $input->getOption('intl-icu');
+ $locales = $input->getOption('locales') ?: $this->enabledLocales;
+ $domains = $input->getOption('domains');
+ $format = $input->getOption('format');
+ $xliffVersion = '1.2';
+
+ if ($intlIcu && !$force) {
+ $io->note('--intl-icu option only has an effect when used with --force. Here, it will be ignored.');
+ }
+
+ switch ($format) {
+ case 'xlf20': $xliffVersion = '2.0';
+ // no break
+ case 'xlf12': $format = 'xlf';
+ }
+
+ $writeOptions = [
+ 'path' => end($this->transPaths),
+ 'xliff_version' => $xliffVersion,
+ ];
+
+ if (!$domains) {
+ $domains = $provider->getDomains();
+ }
+
+ $providerTranslations = $provider->read($domains, $locales);
+
+ if ($force) {
+ foreach ($providerTranslations->getCatalogues() as $catalogue) {
+ $operation = new TargetOperation((new MessageCatalogue($catalogue->getLocale())), $catalogue);
+ if ($intlIcu) {
+ $operation->moveMessagesToIntlDomainsIfPossible();
+ }
+ $this->writer->write($operation->getResult(), $format, $writeOptions);
+ }
+
+ $io->success(sprintf('Local translations has been updated from "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+
+ return 0;
+ }
+
+ $localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);
+
+ // Append pulled translations to local ones.
+ $localTranslations->addBag($providerTranslations->diff($localTranslations));
+
+ foreach ($localTranslations->getCatalogues() as $catalogue) {
+ $this->writer->write($catalogue, $format, $writeOptions);
+ }
+
+ $io->success(sprintf('New translations from "%s" has been written locally (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+
+ return 0;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPushCommand.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPushCommand.php
new file mode 100644
index 0000000..b28d3e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPushCommand.php
@@ -0,0 +1,158 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Translation\Provider\TranslationProviderCollection;
+use Symfony\Component\Translation\Reader\TranslationReaderInterface;
+use Symfony\Component\Translation\TranslatorBag;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+final class TranslationPushCommand extends Command
+{
+ use TranslationTrait;
+
+ protected static $defaultName = 'translation:push';
+ protected static $defaultDescription = 'Push translations to a given provider.';
+
+ private $providers;
+ private $reader;
+ private $transPaths;
+ private $enabledLocales;
+
+ public function __construct(TranslationProviderCollection $providers, TranslationReaderInterface $reader, array $transPaths = [], array $enabledLocales = [])
+ {
+ $this->providers = $providers;
+ $this->reader = $reader;
+ $this->transPaths = $transPaths;
+ $this->enabledLocales = $enabledLocales;
+
+ parent::__construct();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $keys = $this->providers->keys();
+ $defaultProvider = 1 === \count($keys) ? $keys[0] : null;
+
+ $this
+ ->setDefinition([
+ new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to push translations to.', $defaultProvider),
+ new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with local ones (it will delete not synchronized messages).'),
+ new InputOption('delete-missing', null, InputOption::VALUE_NONE, 'Delete translations available on provider but not locally.'),
+ new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to push.'),
+ new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to push.', $this->enabledLocales),
+ ])
+ ->setHelp(<<<'EOF'
+The <info>%command.name%</> command pushes translations to the given provider. Only new
+translations are pushed, existing ones are not overwritten.
+
+You can overwrite existing translations by using the <comment>--force</> flag:
+
+ <info>php %command.full_name% --force provider</>
+
+You can delete provider translations which are not present locally by using the <comment>--delete-missing</> flag:
+
+ <info>php %command.full_name% --delete-missing provider</>
+
+Full example:
+
+ <info>php %command.full_name% provider --force --delete-missing --domains=messages,validators --locales=en</>
+
+This command pushes all translations associated with the <comment>messages</> and <comment>validators</> domains for the <comment>en</> locale.
+Provider translations for the specified domains and locale are deleted if they're not present locally and overwritten if it's the case.
+Provider translations for others domains and locales are ignored.
+EOF
+ )
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $provider = $this->providers->get($input->getArgument('provider'));
+
+ if (!$this->enabledLocales) {
+ throw new InvalidArgumentException(sprintf('You must define "framework.translator.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.', parse_url($provider, \PHP_URL_SCHEME)));
+ }
+
+ $io = new SymfonyStyle($input, $output);
+ $domains = $input->getOption('domains');
+ $locales = $input->getOption('locales');
+ $force = $input->getOption('force');
+ $deleteMissing = $input->getOption('delete-missing');
+
+ $localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);
+
+ if (!$domains) {
+ $domains = $this->getDomainsFromTranslatorBag($localTranslations);
+ }
+
+ if (!$deleteMissing && $force) {
+ $provider->write($localTranslations);
+
+ $io->success(sprintf('All local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+
+ return 0;
+ }
+
+ $providerTranslations = $provider->read($domains, $locales);
+
+ if ($deleteMissing) {
+ $provider->delete($providerTranslations->diff($localTranslations));
+
+ $io->success(sprintf('Missing translations on "%s" has been deleted (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+
+ // Read provider translations again, after missing translations deletion,
+ // to avoid push freshly deleted translations.
+ $providerTranslations = $provider->read($domains, $locales);
+ }
+
+ $translationsToWrite = $localTranslations->diff($providerTranslations);
+
+ if ($force) {
+ $translationsToWrite->addBag($localTranslations->intersect($providerTranslations));
+ }
+
+ $provider->write($translationsToWrite);
+
+ $io->success(sprintf('%s local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', $force ? 'All' : 'New', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+
+ return 0;
+ }
+
+ private function getDomainsFromTranslatorBag(TranslatorBag $translatorBag): array
+ {
+ $domains = [];
+
+ foreach ($translatorBag->getCatalogues() as $catalogue) {
+ $domains += $catalogue->getDomains();
+ }
+
+ return array_unique($domains);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationTrait.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationTrait.php
new file mode 100644
index 0000000..6a2b1ba
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationTrait.php
@@ -0,0 +1,78 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Command;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\MessageCatalogueInterface;
+use Symfony\Component\Translation\TranslatorBag;
+
+/**
+ * @internal
+ */
+trait TranslationTrait
+{
+ private function readLocalTranslations(array $locales, array $domains, array $transPaths): TranslatorBag
+ {
+ $bag = new TranslatorBag();
+
+ foreach ($locales as $locale) {
+ $catalogue = new MessageCatalogue($locale);
+ foreach ($transPaths as $path) {
+ $this->reader->read($path, $catalogue);
+ }
+
+ if ($domains) {
+ foreach ($domains as $domain) {
+ $catalogue = $this->filterCatalogue($catalogue, $domain);
+ $bag->addCatalogue($catalogue);
+ }
+ } else {
+ $bag->addCatalogue($catalogue);
+ }
+ }
+
+ return $bag;
+ }
+
+ private function filterCatalogue(MessageCatalogue $catalogue, string $domain): MessageCatalogue
+ {
+ $filteredCatalogue = new MessageCatalogue($catalogue->getLocale());
+
+ // extract intl-icu messages only
+ $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
+ if ($intlMessages = $catalogue->all($intlDomain)) {
+ $filteredCatalogue->add($intlMessages, $intlDomain);
+ }
+
+ // extract all messages and subtract intl-icu messages
+ if ($messages = array_diff($catalogue->all($domain), $intlMessages)) {
+ $filteredCatalogue->add($messages, $domain);
+ }
+ foreach ($catalogue->getResources() as $resource) {
+ $filteredCatalogue->addResource($resource);
+ }
+
+ if ($metadata = $catalogue->getMetadata('', $intlDomain)) {
+ foreach ($metadata as $k => $v) {
+ $filteredCatalogue->setMetadata($k, $v, $intlDomain);
+ }
+ }
+
+ if ($metadata = $catalogue->getMetadata('', $domain)) {
+ foreach ($metadata as $k => $v) {
+ $filteredCatalogue->setMetadata($k, $v, $domain);
+ }
+ }
+
+ return $filteredCatalogue;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/XliffLintCommand.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/XliffLintCommand.php
new file mode 100644
index 0000000..4117d87
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/XliffLintCommand.php
@@ -0,0 +1,267 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Exception\RuntimeException;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Util\XliffUtils;
+
+/**
+ * Validates XLIFF files syntax and outputs encountered errors.
+ *
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ * @author Robin Chalas <robin.chalas@gmail.com>
+ * @author Javier Eguiluz <javier.eguiluz@gmail.com>
+ */
+class XliffLintCommand extends Command
+{
+ protected static $defaultName = 'lint:xliff';
+ protected static $defaultDescription = 'Lint an XLIFF file and outputs encountered errors';
+
+ private $format;
+ private $displayCorrectFiles;
+ private $directoryIteratorProvider;
+ private $isReadableProvider;
+ private $requireStrictFileNames;
+
+ public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null, bool $requireStrictFileNames = true)
+ {
+ parent::__construct($name);
+
+ $this->directoryIteratorProvider = $directoryIteratorProvider;
+ $this->isReadableProvider = $isReadableProvider;
+ $this->requireStrictFileNames = $requireStrictFileNames;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setDescription(self::$defaultDescription)
+ ->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
+ ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
+ ->setHelp(<<<EOF
+The <info>%command.name%</info> command lints an XLIFF file and outputs to STDOUT
+the first encountered syntax error.
+
+You can validates XLIFF contents passed from STDIN:
+
+ <info>cat filename | php %command.full_name% -</info>
+
+You can also validate the syntax of a file:
+
+ <info>php %command.full_name% filename</info>
+
+Or of a whole directory:
+
+ <info>php %command.full_name% dirname</info>
+ <info>php %command.full_name% dirname --format=json</info>
+
+EOF
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $io = new SymfonyStyle($input, $output);
+ $filenames = (array) $input->getArgument('filename');
+ $this->format = $input->getOption('format');
+ $this->displayCorrectFiles = $output->isVerbose();
+
+ if (['-'] === $filenames) {
+ return $this->display($io, [$this->validate(file_get_contents('php://stdin'))]);
+ }
+
+ if (!$filenames) {
+ throw new RuntimeException('Please provide a filename or pipe file content to STDIN.');
+ }
+
+ $filesInfo = [];
+ foreach ($filenames as $filename) {
+ if (!$this->isReadable($filename)) {
+ throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
+ }
+
+ foreach ($this->getFiles($filename) as $file) {
+ $filesInfo[] = $this->validate(file_get_contents($file), $file);
+ }
+ }
+
+ return $this->display($io, $filesInfo);
+ }
+
+ private function validate(string $content, string $file = null): array
+ {
+ $errors = [];
+
+ // Avoid: Warning DOMDocument::loadXML(): Empty string supplied as input
+ if ('' === trim($content)) {
+ return ['file' => $file, 'valid' => true];
+ }
+
+ $internal = libxml_use_internal_errors(true);
+
+ $document = new \DOMDocument();
+ $document->loadXML($content);
+
+ if (null !== $targetLanguage = $this->getTargetLanguageFromFile($document)) {
+ $normalizedLocalePattern = sprintf('(%s|%s)', preg_quote($targetLanguage, '/'), preg_quote(str_replace('-', '_', $targetLanguage), '/'));
+ // strict file names require translation files to be named '____.locale.xlf'
+ // otherwise, both '____.locale.xlf' and 'locale.____.xlf' are allowed
+ // also, the regexp matching must be case-insensitive, as defined for 'target-language' values
+ // http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#target-language
+ $expectedFilenamePattern = $this->requireStrictFileNames ? sprintf('/^.*\.(?i:%s)\.(?:xlf|xliff)/', $normalizedLocalePattern) : sprintf('/^(?:.*\.(?i:%s)|(?i:%s)\..*)\.(?:xlf|xliff)/', $normalizedLocalePattern, $normalizedLocalePattern);
+
+ if (0 === preg_match($expectedFilenamePattern, basename($file))) {
+ $errors[] = [
+ 'line' => -1,
+ 'column' => -1,
+ 'message' => sprintf('There is a mismatch between the language included in the file name ("%s") and the "%s" value used in the "target-language" attribute of the file.', basename($file), $targetLanguage),
+ ];
+ }
+ }
+
+ foreach (XliffUtils::validateSchema($document) as $xmlError) {
+ $errors[] = [
+ 'line' => $xmlError['line'],
+ 'column' => $xmlError['column'],
+ 'message' => $xmlError['message'],
+ ];
+ }
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($internal);
+
+ return ['file' => $file, 'valid' => 0 === \count($errors), 'messages' => $errors];
+ }
+
+ private function display(SymfonyStyle $io, array $files)
+ {
+ switch ($this->format) {
+ case 'txt':
+ return $this->displayTxt($io, $files);
+ case 'json':
+ return $this->displayJson($io, $files);
+ default:
+ throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format));
+ }
+ }
+
+ private function displayTxt(SymfonyStyle $io, array $filesInfo)
+ {
+ $countFiles = \count($filesInfo);
+ $erroredFiles = 0;
+
+ foreach ($filesInfo as $info) {
+ if ($info['valid'] && $this->displayCorrectFiles) {
+ $io->comment('<info>OK</info>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
+ } elseif (!$info['valid']) {
+ ++$erroredFiles;
+ $io->text('<error> ERROR </error>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
+ $io->listing(array_map(function ($error) {
+ // general document errors have a '-1' line number
+ return -1 === $error['line'] ? $error['message'] : sprintf('Line %d, Column %d: %s', $error['line'], $error['column'], $error['message']);
+ }, $info['messages']));
+ }
+ }
+
+ if (0 === $erroredFiles) {
+ $io->success(sprintf('All %d XLIFF files contain valid syntax.', $countFiles));
+ } else {
+ $io->warning(sprintf('%d XLIFF files have valid syntax and %d contain errors.', $countFiles - $erroredFiles, $erroredFiles));
+ }
+
+ return min($erroredFiles, 1);
+ }
+
+ private function displayJson(SymfonyStyle $io, array $filesInfo)
+ {
+ $errors = 0;
+
+ array_walk($filesInfo, function (&$v) use (&$errors) {
+ $v['file'] = (string) $v['file'];
+ if (!$v['valid']) {
+ ++$errors;
+ }
+ });
+
+ $io->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));
+
+ return min($errors, 1);
+ }
+
+ private function getFiles(string $fileOrDirectory)
+ {
+ if (is_file($fileOrDirectory)) {
+ yield new \SplFileInfo($fileOrDirectory);
+
+ return;
+ }
+
+ foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) {
+ if (!\in_array($file->getExtension(), ['xlf', 'xliff'])) {
+ continue;
+ }
+
+ yield $file;
+ }
+ }
+
+ private function getDirectoryIterator(string $directory)
+ {
+ $default = function ($directory) {
+ return new \RecursiveIteratorIterator(
+ new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS),
+ \RecursiveIteratorIterator::LEAVES_ONLY
+ );
+ };
+
+ if (null !== $this->directoryIteratorProvider) {
+ return ($this->directoryIteratorProvider)($directory, $default);
+ }
+
+ return $default($directory);
+ }
+
+ private function isReadable(string $fileOrDirectory)
+ {
+ $default = function ($fileOrDirectory) {
+ return is_readable($fileOrDirectory);
+ };
+
+ if (null !== $this->isReadableProvider) {
+ return ($this->isReadableProvider)($fileOrDirectory, $default);
+ }
+
+ return $default($fileOrDirectory);
+ }
+
+ private function getTargetLanguageFromFile(\DOMDocument $xliffContents): ?string
+ {
+ foreach ($xliffContents->getElementsByTagName('file')[0]->attributes ?? [] as $attribute) {
+ if ('target-language' === $attribute->nodeName) {
+ return $attribute->nodeValue;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollector/TranslationDataCollector.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollector/TranslationDataCollector.php
new file mode 100644
index 0000000..f8480ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollector/TranslationDataCollector.php
@@ -0,0 +1,172 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DataCollector;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\DataCollector\DataCollector;
+use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
+use Symfony\Component\Translation\DataCollectorTranslator;
+use Symfony\Component\VarDumper\Cloner\Data;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ *
+ * @final
+ */
+class TranslationDataCollector extends DataCollector implements LateDataCollectorInterface
+{
+ private $translator;
+
+ public function __construct(DataCollectorTranslator $translator)
+ {
+ $this->translator = $translator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lateCollect()
+ {
+ $messages = $this->sanitizeCollectedMessages($this->translator->getCollectedMessages());
+
+ $this->data += $this->computeCount($messages);
+ $this->data['messages'] = $messages;
+
+ $this->data = $this->cloneVar($this->data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Throwable $exception = null)
+ {
+ $this->data['locale'] = $this->translator->getLocale();
+ $this->data['fallback_locales'] = $this->translator->getFallbackLocales();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ $this->data = [];
+ }
+
+ /**
+ * @return array|Data
+ */
+ public function getMessages()
+ {
+ return $this->data['messages'] ?? [];
+ }
+
+ /**
+ * @return int
+ */
+ public function getCountMissings()
+ {
+ return $this->data[DataCollectorTranslator::MESSAGE_MISSING] ?? 0;
+ }
+
+ /**
+ * @return int
+ */
+ public function getCountFallbacks()
+ {
+ return $this->data[DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK] ?? 0;
+ }
+
+ /**
+ * @return int
+ */
+ public function getCountDefines()
+ {
+ return $this->data[DataCollectorTranslator::MESSAGE_DEFINED] ?? 0;
+ }
+
+ public function getLocale()
+ {
+ return !empty($this->data['locale']) ? $this->data['locale'] : null;
+ }
+
+ /**
+ * @internal
+ */
+ public function getFallbackLocales()
+ {
+ return (isset($this->data['fallback_locales']) && \count($this->data['fallback_locales']) > 0) ? $this->data['fallback_locales'] : [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'translation';
+ }
+
+ private function sanitizeCollectedMessages(array $messages)
+ {
+ $result = [];
+ foreach ($messages as $key => $message) {
+ $messageId = $message['locale'].$message['domain'].$message['id'];
+
+ if (!isset($result[$messageId])) {
+ $message['count'] = 1;
+ $message['parameters'] = !empty($message['parameters']) ? [$message['parameters']] : [];
+ $messages[$key]['translation'] = $this->sanitizeString($message['translation']);
+ $result[$messageId] = $message;
+ } else {
+ if (!empty($message['parameters'])) {
+ $result[$messageId]['parameters'][] = $message['parameters'];
+ }
+
+ ++$result[$messageId]['count'];
+ }
+
+ unset($messages[$key]);
+ }
+
+ return $result;
+ }
+
+ private function computeCount(array $messages)
+ {
+ $count = [
+ DataCollectorTranslator::MESSAGE_DEFINED => 0,
+ DataCollectorTranslator::MESSAGE_MISSING => 0,
+ DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK => 0,
+ ];
+
+ foreach ($messages as $message) {
+ ++$count[$message['state']];
+ }
+
+ return $count;
+ }
+
+ private function sanitizeString(string $string, int $length = 80)
+ {
+ $string = trim(preg_replace('/\s+/', ' ', $string));
+
+ if (false !== $encoding = mb_detect_encoding($string, null, true)) {
+ if (mb_strlen($string, $encoding) > $length) {
+ return mb_substr($string, 0, $length - 3, $encoding).'...';
+ }
+ } elseif (\strlen($string) > $length) {
+ return substr($string, 0, $length - 3).'...';
+ }
+
+ return $string;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollectorTranslator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollectorTranslator.php
new file mode 100644
index 0000000..c7d3597
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollectorTranslator.php
@@ -0,0 +1,171 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Contracts\Translation\LocaleAwareInterface;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface, WarmableInterface
+{
+ public const MESSAGE_DEFINED = 0;
+ public const MESSAGE_MISSING = 1;
+ public const MESSAGE_EQUALS_FALLBACK = 2;
+
+ /**
+ * @var TranslatorInterface|TranslatorBagInterface
+ */
+ private $translator;
+
+ private $messages = [];
+
+ /**
+ * @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
+ */
+ public function __construct(TranslatorInterface $translator)
+ {
+ if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) {
+ throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator)));
+ }
+
+ $this->translator = $translator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null)
+ {
+ $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale);
+ $this->collectMessage($locale, $domain, $id, $trans, $parameters);
+
+ return $trans;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale(string $locale)
+ {
+ $this->translator->setLocale($locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->translator->getLocale();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue(string $locale = null)
+ {
+ return $this->translator->getCatalogue($locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogues(): array
+ {
+ return $this->translator->getCatalogues();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return string[]
+ */
+ public function warmUp(string $cacheDir)
+ {
+ if ($this->translator instanceof WarmableInterface) {
+ return (array) $this->translator->warmUp($cacheDir);
+ }
+
+ return [];
+ }
+
+ /**
+ * Gets the fallback locales.
+ *
+ * @return array The fallback locales
+ */
+ public function getFallbackLocales()
+ {
+ if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) {
+ return $this->translator->getFallbackLocales();
+ }
+
+ return [];
+ }
+
+ /**
+ * Passes through all unknown calls onto the translator object.
+ */
+ public function __call(string $method, array $args)
+ {
+ return $this->translator->{$method}(...$args);
+ }
+
+ /**
+ * @return array
+ */
+ public function getCollectedMessages()
+ {
+ return $this->messages;
+ }
+
+ private function collectMessage(?string $locale, ?string $domain, string $id, string $translation, ?array $parameters = [])
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $catalogue = $this->translator->getCatalogue($locale);
+ $locale = $catalogue->getLocale();
+ $fallbackLocale = null;
+ if ($catalogue->defines($id, $domain)) {
+ $state = self::MESSAGE_DEFINED;
+ } elseif ($catalogue->has($id, $domain)) {
+ $state = self::MESSAGE_EQUALS_FALLBACK;
+
+ $fallbackCatalogue = $catalogue->getFallbackCatalogue();
+ while ($fallbackCatalogue) {
+ if ($fallbackCatalogue->defines($id, $domain)) {
+ $fallbackLocale = $fallbackCatalogue->getLocale();
+ break;
+ }
+ $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
+ }
+ } else {
+ $state = self::MESSAGE_MISSING;
+ }
+
+ $this->messages[] = [
+ 'locale' => $locale,
+ 'fallbackLocale' => $fallbackLocale,
+ 'domain' => $domain,
+ 'id' => $id,
+ 'translation' => $translation,
+ 'parameters' => $parameters,
+ 'state' => $state,
+ 'transChoiceNumber' => isset($parameters['%count%']) && is_numeric($parameters['%count%']) ? $parameters['%count%'] : null,
+ ];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php
new file mode 100644
index 0000000..6d78342
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Adds tagged translation.formatter services to translation writer.
+ */
+class TranslationDumperPass implements CompilerPassInterface
+{
+ private $writerServiceId;
+ private $dumperTag;
+
+ public function __construct(string $writerServiceId = 'translation.writer', string $dumperTag = 'translation.dumper')
+ {
+ if (1 < \func_num_args()) {
+ trigger_deprecation('symfony/translation', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->writerServiceId = $writerServiceId;
+ $this->dumperTag = $dumperTag;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->writerServiceId)) {
+ return;
+ }
+
+ $definition = $container->getDefinition($this->writerServiceId);
+
+ foreach ($container->findTaggedServiceIds($this->dumperTag, true) as $id => $attributes) {
+ $definition->addMethodCall('addDumper', [$attributes[0]['alias'], new Reference($id)]);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php
new file mode 100644
index 0000000..fab6b20
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Adds tagged translation.extractor services to translation extractor.
+ */
+class TranslationExtractorPass implements CompilerPassInterface
+{
+ private $extractorServiceId;
+ private $extractorTag;
+
+ public function __construct(string $extractorServiceId = 'translation.extractor', string $extractorTag = 'translation.extractor')
+ {
+ if (0 < \func_num_args()) {
+ trigger_deprecation('symfony/translation', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->extractorServiceId = $extractorServiceId;
+ $this->extractorTag = $extractorTag;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->extractorServiceId)) {
+ return;
+ }
+
+ $definition = $container->getDefinition($this->extractorServiceId);
+
+ foreach ($container->findTaggedServiceIds($this->extractorTag, true) as $id => $attributes) {
+ if (!isset($attributes[0]['alias'])) {
+ throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id));
+ }
+
+ $definition->addMethodCall('addExtractor', [$attributes[0]['alias'], new Reference($id)]);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPass.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPass.php
new file mode 100644
index 0000000..c6a1306
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPass.php
@@ -0,0 +1,93 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+class TranslatorPass implements CompilerPassInterface
+{
+ private $translatorServiceId;
+ private $readerServiceId;
+ private $loaderTag;
+ private $debugCommandServiceId;
+ private $updateCommandServiceId;
+
+ public function __construct(string $translatorServiceId = 'translator.default', string $readerServiceId = 'translation.reader', string $loaderTag = 'translation.loader', string $debugCommandServiceId = 'console.command.translation_debug', string $updateCommandServiceId = 'console.command.translation_update')
+ {
+ if (0 < \func_num_args()) {
+ trigger_deprecation('symfony/translation', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->translatorServiceId = $translatorServiceId;
+ $this->readerServiceId = $readerServiceId;
+ $this->loaderTag = $loaderTag;
+ $this->debugCommandServiceId = $debugCommandServiceId;
+ $this->updateCommandServiceId = $updateCommandServiceId;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->translatorServiceId)) {
+ return;
+ }
+
+ $loaders = [];
+ $loaderRefs = [];
+ foreach ($container->findTaggedServiceIds($this->loaderTag, true) as $id => $attributes) {
+ $loaderRefs[$id] = new Reference($id);
+ $loaders[$id][] = $attributes[0]['alias'];
+ if (isset($attributes[0]['legacy-alias'])) {
+ $loaders[$id][] = $attributes[0]['legacy-alias'];
+ }
+ }
+
+ if ($container->hasDefinition($this->readerServiceId)) {
+ $definition = $container->getDefinition($this->readerServiceId);
+ foreach ($loaders as $id => $formats) {
+ foreach ($formats as $format) {
+ $definition->addMethodCall('addLoader', [$format, $loaderRefs[$id]]);
+ }
+ }
+ }
+
+ $container
+ ->findDefinition($this->translatorServiceId)
+ ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs))
+ ->replaceArgument(3, $loaders)
+ ;
+
+ if (!$container->hasParameter('twig.default_path')) {
+ return;
+ }
+
+ $paths = array_keys($container->getDefinition('twig.template_iterator')->getArgument(1));
+ if ($container->hasDefinition($this->debugCommandServiceId)) {
+ $definition = $container->getDefinition($this->debugCommandServiceId);
+ $definition->replaceArgument(4, $container->getParameter('twig.default_path'));
+
+ if (\count($definition->getArguments()) > 6) {
+ $definition->replaceArgument(6, $paths);
+ }
+ }
+ if ($container->hasDefinition($this->updateCommandServiceId)) {
+ $definition = $container->getDefinition($this->updateCommandServiceId);
+ $definition->replaceArgument(5, $container->getParameter('twig.default_path'));
+
+ if (\count($definition->getArguments()) > 7) {
+ $definition->replaceArgument(7, $paths);
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php
new file mode 100644
index 0000000..85b0fa4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php
@@ -0,0 +1,151 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ServiceLocator;
+
+/**
+ * @author Yonel Ceruto <yonelceruto@gmail.com>
+ */
+class TranslatorPathsPass extends AbstractRecursivePass
+{
+ private $translatorServiceId;
+ private $debugCommandServiceId;
+ private $updateCommandServiceId;
+ private $resolverServiceId;
+ private $level = 0;
+ private $paths = [];
+ private $definitions = [];
+ private $controllers = [];
+
+ public function __construct(string $translatorServiceId = 'translator', string $debugCommandServiceId = 'console.command.translation_debug', string $updateCommandServiceId = 'console.command.translation_update', string $resolverServiceId = 'argument_resolver.service')
+ {
+ if (0 < \func_num_args()) {
+ trigger_deprecation('symfony/translation', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->translatorServiceId = $translatorServiceId;
+ $this->debugCommandServiceId = $debugCommandServiceId;
+ $this->updateCommandServiceId = $updateCommandServiceId;
+ $this->resolverServiceId = $resolverServiceId;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->translatorServiceId)) {
+ return;
+ }
+
+ foreach ($this->findControllerArguments($container) as $controller => $argument) {
+ $id = substr($controller, 0, strpos($controller, ':') ?: \strlen($controller));
+ if ($container->hasDefinition($id)) {
+ [$locatorRef] = $argument->getValues();
+ $this->controllers[(string) $locatorRef][$container->getDefinition($id)->getClass()] = true;
+ }
+ }
+
+ try {
+ parent::process($container);
+
+ $paths = [];
+ foreach ($this->paths as $class => $_) {
+ if (($r = $container->getReflectionClass($class)) && !$r->isInterface()) {
+ $paths[] = $r->getFileName();
+ foreach ($r->getTraits() as $trait) {
+ $paths[] = $trait->getFileName();
+ }
+ }
+ }
+ if ($paths) {
+ if ($container->hasDefinition($this->debugCommandServiceId)) {
+ $definition = $container->getDefinition($this->debugCommandServiceId);
+ $definition->replaceArgument(6, array_merge($definition->getArgument(6), $paths));
+ }
+ if ($container->hasDefinition($this->updateCommandServiceId)) {
+ $definition = $container->getDefinition($this->updateCommandServiceId);
+ $definition->replaceArgument(7, array_merge($definition->getArgument(7), $paths));
+ }
+ }
+ } finally {
+ $this->level = 0;
+ $this->paths = [];
+ $this->definitions = [];
+ }
+ }
+
+ protected function processValue($value, bool $isRoot = false)
+ {
+ if ($value instanceof Reference) {
+ if ((string) $value === $this->translatorServiceId) {
+ for ($i = $this->level - 1; $i >= 0; --$i) {
+ $class = $this->definitions[$i]->getClass();
+
+ if (ServiceLocator::class === $class) {
+ if (!isset($this->controllers[$this->currentId])) {
+ continue;
+ }
+ foreach ($this->controllers[$this->currentId] as $class => $_) {
+ $this->paths[$class] = true;
+ }
+ } else {
+ $this->paths[$class] = true;
+ }
+
+ break;
+ }
+ }
+
+ return $value;
+ }
+
+ if ($value instanceof Definition) {
+ $this->definitions[$this->level++] = $value;
+ $value = parent::processValue($value, $isRoot);
+ unset($this->definitions[--$this->level]);
+
+ return $value;
+ }
+
+ return parent::processValue($value, $isRoot);
+ }
+
+ private function findControllerArguments(ContainerBuilder $container): array
+ {
+ if ($container->hasDefinition($this->resolverServiceId)) {
+ $argument = $container->getDefinition($this->resolverServiceId)->getArgument(0);
+ if ($argument instanceof Reference) {
+ $argument = $container->getDefinition($argument);
+ }
+
+ return $argument->getArgument(0);
+ }
+
+ if ($container->hasDefinition('debug.'.$this->resolverServiceId)) {
+ $argument = $container->getDefinition('debug.'.$this->resolverServiceId)->getArgument(0);
+ if ($argument instanceof Reference) {
+ $argument = $container->getDefinition($argument);
+ }
+ $argument = $argument->getArgument(0);
+ if ($argument instanceof Reference) {
+ $argument = $container->getDefinition($argument);
+ }
+
+ return $argument->getArgument(0);
+ }
+
+ return [];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/CsvFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/CsvFileDumper.php
new file mode 100644
index 0000000..0c8589a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/CsvFileDumper.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * CsvFileDumper generates a csv formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class CsvFileDumper extends FileDumper
+{
+ private $delimiter = ';';
+ private $enclosure = '"';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $handle = fopen('php://memory', 'r+');
+
+ foreach ($messages->all($domain) as $source => $target) {
+ fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure);
+ }
+
+ rewind($handle);
+ $output = stream_get_contents($handle);
+ fclose($handle);
+
+ return $output;
+ }
+
+ /**
+ * Sets the delimiter and escape character for CSV.
+ */
+ public function setCsvControl(string $delimiter = ';', string $enclosure = '"')
+ {
+ $this->delimiter = $delimiter;
+ $this->enclosure = $enclosure;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'csv';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/DumperInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/DumperInterface.php
new file mode 100644
index 0000000..7cdaef5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/DumperInterface.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * DumperInterface is the interface implemented by all translation dumpers.
+ * There is no common option.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+interface DumperInterface
+{
+ /**
+ * Dumps the message catalogue.
+ *
+ * @param array $options Options that are used by the dumper
+ */
+ public function dump(MessageCatalogue $messages, array $options = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/FileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/FileDumper.php
new file mode 100644
index 0000000..e257e72
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/FileDumper.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s).
+ *
+ * Options:
+ * - path (mandatory): the directory where the files should be saved
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+abstract class FileDumper implements DumperInterface
+{
+ /**
+ * A template for the relative paths to files.
+ *
+ * @var string
+ */
+ protected $relativePathTemplate = '%domain%.%locale%.%extension%';
+
+ /**
+ * Sets the template for the relative paths to files.
+ *
+ * @param string $relativePathTemplate A template for the relative paths to files
+ */
+ public function setRelativePathTemplate(string $relativePathTemplate)
+ {
+ $this->relativePathTemplate = $relativePathTemplate;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dump(MessageCatalogue $messages, array $options = [])
+ {
+ if (!\array_key_exists('path', $options)) {
+ throw new InvalidArgumentException('The file dumper needs a path option.');
+ }
+
+ // save a file for each domain
+ foreach ($messages->getDomains() as $domain) {
+ $fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale());
+ if (!file_exists($fullpath)) {
+ $directory = \dirname($fullpath);
+ if (!file_exists($directory) && !@mkdir($directory, 0777, true)) {
+ throw new RuntimeException(sprintf('Unable to create directory "%s".', $directory));
+ }
+ }
+
+ $intlDomain = $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX;
+ $intlMessages = $messages->all($intlDomain);
+
+ if ($intlMessages) {
+ $intlPath = $options['path'].'/'.$this->getRelativePath($intlDomain, $messages->getLocale());
+ file_put_contents($intlPath, $this->formatCatalogue($messages, $intlDomain, $options));
+
+ $messages->replace([], $intlDomain);
+
+ try {
+ if ($messages->all($domain)) {
+ file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
+ }
+ continue;
+ } finally {
+ $messages->replace($intlMessages, $intlDomain);
+ }
+ }
+
+ file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
+ }
+ }
+
+ /**
+ * Transforms a domain of a message catalogue to its string representation.
+ *
+ * @return string representation
+ */
+ abstract public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []);
+
+ /**
+ * Gets the file extension of the dumper.
+ *
+ * @return string file extension
+ */
+ abstract protected function getExtension();
+
+ /**
+ * Gets the relative file path using the template.
+ */
+ private function getRelativePath(string $domain, string $locale): string
+ {
+ return strtr($this->relativePathTemplate, [
+ '%domain%' => $domain,
+ '%locale%' => $locale,
+ '%extension%' => $this->getExtension(),
+ ]);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IcuResFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IcuResFileDumper.php
new file mode 100644
index 0000000..cdc5991
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IcuResFileDumper.php
@@ -0,0 +1,104 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class IcuResFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $relativePathTemplate = '%domain%/%locale%.%extension%';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $data = $indexes = $resources = '';
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $indexes .= pack('v', \strlen($data) + 28);
+ $data .= $source."\0";
+ }
+
+ $data .= $this->writePadding($data);
+
+ $keyTop = $this->getPosition($data);
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $resources .= pack('V', $this->getPosition($data));
+
+ $data .= pack('V', \strlen($target))
+ .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8')
+ .$this->writePadding($data)
+ ;
+ }
+
+ $resOffset = $this->getPosition($data);
+
+ $data .= pack('v', \count($messages->all($domain)))
+ .$indexes
+ .$this->writePadding($data)
+ .$resources
+ ;
+
+ $bundleTop = $this->getPosition($data);
+
+ $root = pack('V7',
+ $resOffset + (2 << 28), // Resource Offset + Resource Type
+ 6, // Index length
+ $keyTop, // Index keys top
+ $bundleTop, // Index resources top
+ $bundleTop, // Index bundle top
+ \count($messages->all($domain)), // Index max table length
+ 0 // Index attributes
+ );
+
+ $header = pack('vC2v4C12@32',
+ 32, // Header size
+ 0xDA, 0x27, // Magic number 1 and 2
+ 20, 0, 0, 2, // Rest of the header, ..., Size of a char
+ 0x52, 0x65, 0x73, 0x42, // Data format identifier
+ 1, 2, 0, 0, // Data version
+ 1, 4, 0, 0 // Unicode version
+ );
+
+ return $header.$root.$data;
+ }
+
+ private function writePadding(string $data): ?string
+ {
+ $padding = \strlen($data) % 4;
+
+ return $padding ? str_repeat("\xAA", 4 - $padding) : null;
+ }
+
+ private function getPosition(string $data)
+ {
+ return (\strlen($data) + 28) / 4;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'res';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IniFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IniFileDumper.php
new file mode 100644
index 0000000..93c900a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IniFileDumper.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IniFileDumper generates an ini formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class IniFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $output = '';
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $escapeTarget = str_replace('"', '\"', $target);
+ $output .= $source.'="'.$escapeTarget."\"\n";
+ }
+
+ return $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'ini';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/JsonFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/JsonFileDumper.php
new file mode 100644
index 0000000..34c0b56
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/JsonFileDumper.php
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * JsonFileDumper generates an json formatted string representation of a message catalogue.
+ *
+ * @author singles
+ */
+class JsonFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $flags = $options['json_encoding'] ?? \JSON_PRETTY_PRINT;
+
+ return json_encode($messages->all($domain), $flags);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'json';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/MoFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/MoFileDumper.php
new file mode 100644
index 0000000..54d0da8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/MoFileDumper.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\Loader\MoFileLoader;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * MoFileDumper generates a gettext formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class MoFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $sources = $targets = $sourceOffsets = $targetOffsets = '';
+ $offsets = [];
+ $size = 0;
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $offsets[] = array_map('strlen', [$sources, $source, $targets, $target]);
+ $sources .= "\0".$source;
+ $targets .= "\0".$target;
+ ++$size;
+ }
+
+ $header = [
+ 'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC,
+ 'formatRevision' => 0,
+ 'count' => $size,
+ 'offsetId' => MoFileLoader::MO_HEADER_SIZE,
+ 'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size),
+ 'sizeHashes' => 0,
+ 'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size),
+ ];
+
+ $sourcesSize = \strlen($sources);
+ $sourcesStart = $header['offsetHashes'] + 1;
+
+ foreach ($offsets as $offset) {
+ $sourceOffsets .= $this->writeLong($offset[1])
+ .$this->writeLong($offset[0] + $sourcesStart);
+ $targetOffsets .= $this->writeLong($offset[3])
+ .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize);
+ }
+
+ $output = implode('', array_map([$this, 'writeLong'], $header))
+ .$sourceOffsets
+ .$targetOffsets
+ .$sources
+ .$targets
+ ;
+
+ return $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'mo';
+ }
+
+ private function writeLong($str): string
+ {
+ return pack('V*', $str);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PhpFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PhpFileDumper.php
new file mode 100644
index 0000000..6163b52
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PhpFileDumper.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * PhpFileDumper generates PHP files from a message catalogue.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class PhpFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ return "<?php\n\nreturn ".var_export($messages->all($domain), true).";\n";
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'php';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PoFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PoFileDumper.php
new file mode 100644
index 0000000..0d82281
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PoFileDumper.php
@@ -0,0 +1,137 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * PoFileDumper generates a gettext formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class PoFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $output = 'msgid ""'."\n";
+ $output .= 'msgstr ""'."\n";
+ $output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n";
+ $output .= '"Content-Transfer-Encoding: 8bit\n"'."\n";
+ $output .= '"Language: '.$messages->getLocale().'\n"'."\n";
+ $output .= "\n";
+
+ $newLine = false;
+ foreach ($messages->all($domain) as $source => $target) {
+ if ($newLine) {
+ $output .= "\n";
+ } else {
+ $newLine = true;
+ }
+ $metadata = $messages->getMetadata($source, $domain);
+
+ if (isset($metadata['comments'])) {
+ $output .= $this->formatComments($metadata['comments']);
+ }
+ if (isset($metadata['flags'])) {
+ $output .= $this->formatComments(implode(',', (array) $metadata['flags']), ',');
+ }
+ if (isset($metadata['sources'])) {
+ $output .= $this->formatComments(implode(' ', (array) $metadata['sources']), ':');
+ }
+
+ $sourceRules = $this->getStandardRules($source);
+ $targetRules = $this->getStandardRules($target);
+ if (2 == \count($sourceRules) && [] !== $targetRules) {
+ $output .= sprintf('msgid "%s"'."\n", $this->escape($sourceRules[0]));
+ $output .= sprintf('msgid_plural "%s"'."\n", $this->escape($sourceRules[1]));
+ foreach ($targetRules as $i => $targetRule) {
+ $output .= sprintf('msgstr[%d] "%s"'."\n", $i, $this->escape($targetRule));
+ }
+ } else {
+ $output .= sprintf('msgid "%s"'."\n", $this->escape($source));
+ $output .= sprintf('msgstr "%s"'."\n", $this->escape($target));
+ }
+ }
+
+ return $output;
+ }
+
+ private function getStandardRules(string $id)
+ {
+ // Partly copied from TranslatorTrait::trans.
+ $parts = [];
+ if (preg_match('/^\|++$/', $id)) {
+ $parts = explode('|', $id);
+ } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) {
+ $parts = $matches[0];
+ }
+
+ $intervalRegexp = <<<'EOF'
+/^(?P<interval>
+ ({\s*
+ (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
+ \s*})
+
+ |
+
+ (?P<left_delimiter>[\[\]])
+ \s*
+ (?P<left>-Inf|\-?\d+(\.\d+)?)
+ \s*,\s*
+ (?P<right>\+?Inf|\-?\d+(\.\d+)?)
+ \s*
+ (?P<right_delimiter>[\[\]])
+)\s*(?P<message>.*?)$/xs
+EOF;
+
+ $standardRules = [];
+ foreach ($parts as $part) {
+ $part = trim(str_replace('||', '|', $part));
+
+ if (preg_match($intervalRegexp, $part)) {
+ // Explicit rule is not a standard rule.
+ return [];
+ } else {
+ $standardRules[] = $part;
+ }
+ }
+
+ return $standardRules;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'po';
+ }
+
+ private function escape(string $str): string
+ {
+ return addcslashes($str, "\0..\37\42\134");
+ }
+
+ private function formatComments($comments, string $prefix = ''): ?string
+ {
+ $output = null;
+
+ foreach ((array) $comments as $comment) {
+ $output .= sprintf('#%s %s'."\n", $prefix, $comment);
+ }
+
+ return $output;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/QtFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/QtFileDumper.php
new file mode 100644
index 0000000..406e9f0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/QtFileDumper.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * QtFileDumper generates ts files from a message catalogue.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class QtFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $dom = new \DOMDocument('1.0', 'utf-8');
+ $dom->formatOutput = true;
+ $ts = $dom->appendChild($dom->createElement('TS'));
+ $context = $ts->appendChild($dom->createElement('context'));
+ $context->appendChild($dom->createElement('name', $domain));
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $message = $context->appendChild($dom->createElement('message'));
+ $metadata = $messages->getMetadata($source, $domain);
+ if (isset($metadata['sources'])) {
+ foreach ((array) $metadata['sources'] as $location) {
+ $loc = explode(':', $location, 2);
+ $location = $message->appendChild($dom->createElement('location'));
+ $location->setAttribute('filename', $loc[0]);
+ if (isset($loc[1])) {
+ $location->setAttribute('line', $loc[1]);
+ }
+ }
+ }
+ $message->appendChild($dom->createElement('source', $source));
+ $message->appendChild($dom->createElement('translation', $target));
+ }
+
+ return $dom->saveXML();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'ts';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/XliffFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/XliffFileDumper.php
new file mode 100644
index 0000000..f7dbdcd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/XliffFileDumper.php
@@ -0,0 +1,203 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * XliffFileDumper generates xliff files from a message catalogue.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class XliffFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $xliffVersion = '1.2';
+ if (\array_key_exists('xliff_version', $options)) {
+ $xliffVersion = $options['xliff_version'];
+ }
+
+ if (\array_key_exists('default_locale', $options)) {
+ $defaultLocale = $options['default_locale'];
+ } else {
+ $defaultLocale = \Locale::getDefault();
+ }
+
+ if ('1.2' === $xliffVersion) {
+ return $this->dumpXliff1($defaultLocale, $messages, $domain, $options);
+ }
+ if ('2.0' === $xliffVersion) {
+ return $this->dumpXliff2($defaultLocale, $messages, $domain);
+ }
+
+ throw new InvalidArgumentException(sprintf('No support implemented for dumping XLIFF version "%s".', $xliffVersion));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'xlf';
+ }
+
+ private function dumpXliff1(string $defaultLocale, MessageCatalogue $messages, ?string $domain, array $options = [])
+ {
+ $toolInfo = ['tool-id' => 'symfony', 'tool-name' => 'Symfony'];
+ if (\array_key_exists('tool_info', $options)) {
+ $toolInfo = array_merge($toolInfo, $options['tool_info']);
+ }
+
+ $dom = new \DOMDocument('1.0', 'utf-8');
+ $dom->formatOutput = true;
+
+ $xliff = $dom->appendChild($dom->createElement('xliff'));
+ $xliff->setAttribute('version', '1.2');
+ $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2');
+
+ $xliffFile = $xliff->appendChild($dom->createElement('file'));
+ $xliffFile->setAttribute('source-language', str_replace('_', '-', $defaultLocale));
+ $xliffFile->setAttribute('target-language', str_replace('_', '-', $messages->getLocale()));
+ $xliffFile->setAttribute('datatype', 'plaintext');
+ $xliffFile->setAttribute('original', 'file.ext');
+
+ $xliffHead = $xliffFile->appendChild($dom->createElement('header'));
+ $xliffTool = $xliffHead->appendChild($dom->createElement('tool'));
+ foreach ($toolInfo as $id => $value) {
+ $xliffTool->setAttribute($id, $value);
+ }
+
+ $xliffBody = $xliffFile->appendChild($dom->createElement('body'));
+ foreach ($messages->all($domain) as $source => $target) {
+ $translation = $dom->createElement('trans-unit');
+
+ $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._'));
+ $translation->setAttribute('resname', $source);
+
+ $s = $translation->appendChild($dom->createElement('source'));
+ $s->appendChild($dom->createTextNode($source));
+
+ // Does the target contain characters requiring a CDATA section?
+ $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);
+
+ $targetElement = $dom->createElement('target');
+ $metadata = $messages->getMetadata($source, $domain);
+ if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
+ foreach ($metadata['target-attributes'] as $name => $value) {
+ $targetElement->setAttribute($name, $value);
+ }
+ }
+ $t = $translation->appendChild($targetElement);
+ $t->appendChild($text);
+
+ if ($this->hasMetadataArrayInfo('notes', $metadata)) {
+ foreach ($metadata['notes'] as $note) {
+ if (!isset($note['content'])) {
+ continue;
+ }
+
+ $n = $translation->appendChild($dom->createElement('note'));
+ $n->appendChild($dom->createTextNode($note['content']));
+
+ if (isset($note['priority'])) {
+ $n->setAttribute('priority', $note['priority']);
+ }
+
+ if (isset($note['from'])) {
+ $n->setAttribute('from', $note['from']);
+ }
+ }
+ }
+
+ $xliffBody->appendChild($translation);
+ }
+
+ return $dom->saveXML();
+ }
+
+ private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ?string $domain)
+ {
+ $dom = new \DOMDocument('1.0', 'utf-8');
+ $dom->formatOutput = true;
+
+ $xliff = $dom->appendChild($dom->createElement('xliff'));
+ $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:2.0');
+ $xliff->setAttribute('version', '2.0');
+ $xliff->setAttribute('srcLang', str_replace('_', '-', $defaultLocale));
+ $xliff->setAttribute('trgLang', str_replace('_', '-', $messages->getLocale()));
+
+ $xliffFile = $xliff->appendChild($dom->createElement('file'));
+ if (str_ends_with($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
+ $xliffFile->setAttribute('id', substr($domain, 0, -\strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX)).'.'.$messages->getLocale());
+ } else {
+ $xliffFile->setAttribute('id', $domain.'.'.$messages->getLocale());
+ }
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $translation = $dom->createElement('unit');
+ $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._'));
+
+ if (\strlen($source) <= 80) {
+ $translation->setAttribute('name', $source);
+ }
+
+ $metadata = $messages->getMetadata($source, $domain);
+
+ // Add notes section
+ if ($this->hasMetadataArrayInfo('notes', $metadata)) {
+ $notesElement = $dom->createElement('notes');
+ foreach ($metadata['notes'] as $note) {
+ $n = $dom->createElement('note');
+ $n->appendChild($dom->createTextNode($note['content'] ?? ''));
+ unset($note['content']);
+
+ foreach ($note as $name => $value) {
+ $n->setAttribute($name, $value);
+ }
+ $notesElement->appendChild($n);
+ }
+ $translation->appendChild($notesElement);
+ }
+
+ $segment = $translation->appendChild($dom->createElement('segment'));
+
+ $s = $segment->appendChild($dom->createElement('source'));
+ $s->appendChild($dom->createTextNode($source));
+
+ // Does the target contain characters requiring a CDATA section?
+ $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);
+
+ $targetElement = $dom->createElement('target');
+ if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
+ foreach ($metadata['target-attributes'] as $name => $value) {
+ $targetElement->setAttribute($name, $value);
+ }
+ }
+ $t = $segment->appendChild($targetElement);
+ $t->appendChild($text);
+
+ $xliffFile->appendChild($translation);
+ }
+
+ return $dom->saveXML();
+ }
+
+ private function hasMetadataArrayInfo(string $key, array $metadata = null): bool
+ {
+ return is_iterable($metadata[$key] ?? null);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/YamlFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/YamlFileDumper.php
new file mode 100644
index 0000000..0b21e8c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/YamlFileDumper.php
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\Exception\LogicException;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Util\ArrayConverter;
+use Symfony\Component\Yaml\Yaml;
+
+/**
+ * YamlFileDumper generates yaml files from a message catalogue.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class YamlFileDumper extends FileDumper
+{
+ private $extension;
+
+ public function __construct(string $extension = 'yml')
+ {
+ $this->extension = $extension;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ if (!class_exists(Yaml::class)) {
+ throw new LogicException('Dumping translations in the YAML format requires the Symfony Yaml component.');
+ }
+
+ $data = $messages->all($domain);
+
+ if (isset($options['as_tree']) && $options['as_tree']) {
+ $data = ArrayConverter::expandToTree($data);
+ }
+
+ if (isset($options['inline']) && ($inline = (int) $options['inline']) > 0) {
+ return Yaml::dump($data, $inline);
+ }
+
+ return Yaml::dump($data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return $this->extension;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ExceptionInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..8f9c54e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ExceptionInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Exception interface for all exceptions thrown by the component.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface ExceptionInterface extends \Throwable
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/IncompleteDsnException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/IncompleteDsnException.php
new file mode 100644
index 0000000..cb0ce02
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/IncompleteDsnException.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+class IncompleteDsnException extends InvalidArgumentException
+{
+ public function __construct(string $message, string $dsn = null, \Throwable $previous = null)
+ {
+ if ($dsn) {
+ $message = sprintf('Invalid "%s" provider DSN: ', $dsn).$message;
+ }
+
+ parent::__construct($message, 0, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidArgumentException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000..90d0669
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidArgumentException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Base InvalidArgumentException for the Translation component.
+ *
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidResourceException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidResourceException.php
new file mode 100644
index 0000000..cf07943
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidResourceException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Thrown when a resource cannot be loaded.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/LogicException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/LogicException.php
new file mode 100644
index 0000000..9019c7e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/LogicException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Base LogicException for Translation component.
+ *
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class LogicException extends \LogicException implements ExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/MissingRequiredOptionException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/MissingRequiredOptionException.php
new file mode 100644
index 0000000..2b5f808
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/MissingRequiredOptionException.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * @author Oskar Stark <oskarstark@googlemail.com>
+ */
+class MissingRequiredOptionException extends IncompleteDsnException
+{
+ public function __construct(string $option, string $dsn = null, \Throwable $previous = null)
+ {
+ $message = sprintf('The option "%s" is required but missing.', $option);
+
+ parent::__construct($message, $dsn, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/NotFoundResourceException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/NotFoundResourceException.php
new file mode 100644
index 0000000..cff73ae
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/NotFoundResourceException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Thrown when a resource does not exist.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderException.php
new file mode 100644
index 0000000..659c6d7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderException.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+use Symfony\Contracts\HttpClient\ResponseInterface;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @experimental in 5.3
+ */
+class ProviderException extends RuntimeException implements ProviderExceptionInterface
+{
+ private $response;
+ private $debug;
+
+ public function __construct(string $message, ResponseInterface $response, int $code = 0, \Exception $previous = null)
+ {
+ $this->response = $response;
+ $this->debug .= $response->getInfo('debug') ?? '';
+
+ parent::__construct($message, $code, $previous);
+ }
+
+ public function getResponse(): ResponseInterface
+ {
+ return $this->response;
+ }
+
+ public function getDebug(): string
+ {
+ return $this->debug;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderExceptionInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderExceptionInterface.php
new file mode 100644
index 0000000..8cf1c51
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderExceptionInterface.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @experimental in 5.3
+ */
+interface ProviderExceptionInterface extends ExceptionInterface
+{
+ /*
+ * Returns debug info coming from the Symfony\Contracts\HttpClient\ResponseInterface
+ */
+ public function getDebug(): string;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/RuntimeException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/RuntimeException.php
new file mode 100644
index 0000000..dcd7940
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/RuntimeException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Base RuntimeException for the Translation component.
+ *
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/UnsupportedSchemeException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/UnsupportedSchemeException.php
new file mode 100644
index 0000000..7fbaa8f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/UnsupportedSchemeException.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+use Symfony\Component\Translation\Bridge;
+use Symfony\Component\Translation\Provider\Dsn;
+
+class UnsupportedSchemeException extends LogicException
+{
+ private const SCHEME_TO_PACKAGE_MAP = [
+ 'crowdin' => [
+ 'class' => Bridge\Crowdin\CrowdinProviderFactory::class,
+ 'package' => 'symfony/crowdin-translation-provider',
+ ],
+ 'loco' => [
+ 'class' => Bridge\Loco\LocoProviderFactory::class,
+ 'package' => 'symfony/loco-translation-provider',
+ ],
+ 'lokalise' => [
+ 'class' => Bridge\Lokalise\LokaliseProviderFactory::class,
+ 'package' => 'symfony/lokalise-translation-provider',
+ ],
+ ];
+
+ public function __construct(Dsn $dsn, string $name = null, array $supported = [])
+ {
+ $provider = $dsn->getScheme();
+ if (false !== $pos = strpos($provider, '+')) {
+ $provider = substr($provider, 0, $pos);
+ }
+ $package = self::SCHEME_TO_PACKAGE_MAP[$provider] ?? null;
+ if ($package && !class_exists($package['class'])) {
+ parent::__construct(sprintf('Unable to synchronize translations via "%s" as the provider is not installed; try running "composer require %s".', $provider, $package['package']));
+
+ return;
+ }
+
+ $message = sprintf('The "%s" scheme is not supported', $dsn->getScheme());
+ if ($name && $supported) {
+ $message .= sprintf('; supported schemes for translation provider "%s" are: "%s"', $name, implode('", "', $supported));
+ }
+
+ parent::__construct($message.'.');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/AbstractFileExtractor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/AbstractFileExtractor.php
new file mode 100644
index 0000000..729dd17
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/AbstractFileExtractor.php
@@ -0,0 +1,76 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+
+/**
+ * Base class used by classes that extract translation messages from files.
+ *
+ * @author Marcos D. Sánchez <marcosdsanchez@gmail.com>
+ */
+abstract class AbstractFileExtractor
+{
+ /**
+ * @param string|iterable $resource Files, a file or a directory
+ *
+ * @return iterable
+ */
+ protected function extractFiles($resource)
+ {
+ if (is_iterable($resource)) {
+ $files = [];
+ foreach ($resource as $file) {
+ if ($this->canBeExtracted($file)) {
+ $files[] = $this->toSplFileInfo($file);
+ }
+ }
+ } elseif (is_file($resource)) {
+ $files = $this->canBeExtracted($resource) ? [$this->toSplFileInfo($resource)] : [];
+ } else {
+ $files = $this->extractFromDirectory($resource);
+ }
+
+ return $files;
+ }
+
+ private function toSplFileInfo(string $file): \SplFileInfo
+ {
+ return new \SplFileInfo($file);
+ }
+
+ /**
+ * @return bool
+ *
+ * @throws InvalidArgumentException
+ */
+ protected function isFile(string $file)
+ {
+ if (!is_file($file)) {
+ throw new InvalidArgumentException(sprintf('The "%s" file does not exist.', $file));
+ }
+
+ return true;
+ }
+
+ /**
+ * @return bool
+ */
+ abstract protected function canBeExtracted(string $file);
+
+ /**
+ * @param string|array $resource Files, a file or a directory
+ *
+ * @return iterable files to be extracted
+ */
+ abstract protected function extractFromDirectory($resource);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ChainExtractor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ChainExtractor.php
new file mode 100644
index 0000000..95dcf15
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ChainExtractor.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * ChainExtractor extracts translation messages from template files.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class ChainExtractor implements ExtractorInterface
+{
+ /**
+ * The extractors.
+ *
+ * @var ExtractorInterface[]
+ */
+ private $extractors = [];
+
+ /**
+ * Adds a loader to the translation extractor.
+ */
+ public function addExtractor(string $format, ExtractorInterface $extractor)
+ {
+ $this->extractors[$format] = $extractor;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPrefix(string $prefix)
+ {
+ foreach ($this->extractors as $extractor) {
+ $extractor->setPrefix($prefix);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function extract($directory, MessageCatalogue $catalogue)
+ {
+ foreach ($this->extractors as $extractor) {
+ $extractor->extract($directory, $catalogue);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ExtractorInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ExtractorInterface.php
new file mode 100644
index 0000000..e1db8a9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ExtractorInterface.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * Extracts translation messages from a directory or files to the catalogue.
+ * New found messages are injected to the catalogue using the prefix.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+interface ExtractorInterface
+{
+ /**
+ * Extracts translation messages from files, a file or a directory to the catalogue.
+ *
+ * @param string|iterable<string> $resource Files, a file or a directory
+ */
+ public function extract($resource, MessageCatalogue $catalogue);
+
+ /**
+ * Sets the prefix that should be used for new found messages.
+ */
+ public function setPrefix(string $prefix);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpExtractor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpExtractor.php
new file mode 100644
index 0000000..c5efb5f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpExtractor.php
@@ -0,0 +1,336 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * PhpExtractor extracts translation messages from a PHP template.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface
+{
+ public const MESSAGE_TOKEN = 300;
+ public const METHOD_ARGUMENTS_TOKEN = 1000;
+ public const DOMAIN_TOKEN = 1001;
+
+ /**
+ * Prefix for new found message.
+ *
+ * @var string
+ */
+ private $prefix = '';
+
+ /**
+ * The sequence that captures translation messages.
+ *
+ * @var array
+ */
+ protected $sequences = [
+ [
+ '->',
+ 'trans',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ],
+ [
+ '->',
+ 'trans',
+ '(',
+ self::MESSAGE_TOKEN,
+ ],
+ [
+ 'new',
+ 'TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ],
+ [
+ 'new',
+ 'TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ],
+ [
+ 'new',
+ '\\',
+ 'Symfony',
+ '\\',
+ 'Component',
+ '\\',
+ 'Translation',
+ '\\',
+ 'TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ],
+ [
+ 'new',
+ '\Symfony\Component\Translation\TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ],
+ [
+ 'new',
+ '\\',
+ 'Symfony',
+ '\\',
+ 'Component',
+ '\\',
+ 'Translation',
+ '\\',
+ 'TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ],
+ [
+ 'new',
+ '\Symfony\Component\Translation\TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ],
+ [
+ 't',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ],
+ [
+ 't',
+ '(',
+ self::MESSAGE_TOKEN,
+ ],
+ ];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function extract($resource, MessageCatalogue $catalog)
+ {
+ $files = $this->extractFiles($resource);
+ foreach ($files as $file) {
+ $this->parseTokens(token_get_all(file_get_contents($file)), $catalog, $file);
+
+ gc_mem_caches();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPrefix(string $prefix)
+ {
+ $this->prefix = $prefix;
+ }
+
+ /**
+ * Normalizes a token.
+ *
+ * @param mixed $token
+ *
+ * @return string|null
+ */
+ protected function normalizeToken($token)
+ {
+ if (isset($token[1]) && 'b"' !== $token) {
+ return $token[1];
+ }
+
+ return $token;
+ }
+
+ /**
+ * Seeks to a non-whitespace token.
+ */
+ private function seekToNextRelevantToken(\Iterator $tokenIterator)
+ {
+ for (; $tokenIterator->valid(); $tokenIterator->next()) {
+ $t = $tokenIterator->current();
+ if (\T_WHITESPACE !== $t[0]) {
+ break;
+ }
+ }
+ }
+
+ private function skipMethodArgument(\Iterator $tokenIterator)
+ {
+ $openBraces = 0;
+
+ for (; $tokenIterator->valid(); $tokenIterator->next()) {
+ $t = $tokenIterator->current();
+
+ if ('[' === $t[0] || '(' === $t[0]) {
+ ++$openBraces;
+ }
+
+ if (']' === $t[0] || ')' === $t[0]) {
+ --$openBraces;
+ }
+
+ if ((0 === $openBraces && ',' === $t[0]) || (-1 === $openBraces && ')' === $t[0])) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Extracts the message from the iterator while the tokens
+ * match allowed message tokens.
+ */
+ private function getValue(\Iterator $tokenIterator)
+ {
+ $message = '';
+ $docToken = '';
+ $docPart = '';
+
+ for (; $tokenIterator->valid(); $tokenIterator->next()) {
+ $t = $tokenIterator->current();
+ if ('.' === $t) {
+ // Concatenate with next token
+ continue;
+ }
+ if (!isset($t[1])) {
+ break;
+ }
+
+ switch ($t[0]) {
+ case \T_START_HEREDOC:
+ $docToken = $t[1];
+ break;
+ case \T_ENCAPSED_AND_WHITESPACE:
+ case \T_CONSTANT_ENCAPSED_STRING:
+ if ('' === $docToken) {
+ $message .= PhpStringTokenParser::parse($t[1]);
+ } else {
+ $docPart = $t[1];
+ }
+ break;
+ case \T_END_HEREDOC:
+ if ($indentation = strspn($t[1], ' ')) {
+ $docPartWithLineBreaks = $docPart;
+ $docPart = '';
+
+ foreach (preg_split('~(\r\n|\n|\r)~', $docPartWithLineBreaks, -1, \PREG_SPLIT_DELIM_CAPTURE) as $str) {
+ if (\in_array($str, ["\r\n", "\n", "\r"], true)) {
+ $docPart .= $str;
+ } else {
+ $docPart .= substr($str, $indentation);
+ }
+ }
+ }
+
+ $message .= PhpStringTokenParser::parseDocString($docToken, $docPart);
+ $docToken = '';
+ $docPart = '';
+ break;
+ case \T_WHITESPACE:
+ break;
+ default:
+ break 2;
+ }
+ }
+
+ return $message;
+ }
+
+ /**
+ * Extracts trans message from PHP tokens.
+ */
+ protected function parseTokens(array $tokens, MessageCatalogue $catalog, string $filename)
+ {
+ $tokenIterator = new \ArrayIterator($tokens);
+
+ for ($key = 0; $key < $tokenIterator->count(); ++$key) {
+ foreach ($this->sequences as $sequence) {
+ $message = '';
+ $domain = 'messages';
+ $tokenIterator->seek($key);
+
+ foreach ($sequence as $sequenceKey => $item) {
+ $this->seekToNextRelevantToken($tokenIterator);
+
+ if ($this->normalizeToken($tokenIterator->current()) === $item) {
+ $tokenIterator->next();
+ continue;
+ } elseif (self::MESSAGE_TOKEN === $item) {
+ $message = $this->getValue($tokenIterator);
+
+ if (\count($sequence) === ($sequenceKey + 1)) {
+ break;
+ }
+ } elseif (self::METHOD_ARGUMENTS_TOKEN === $item) {
+ $this->skipMethodArgument($tokenIterator);
+ } elseif (self::DOMAIN_TOKEN === $item) {
+ $domainToken = $this->getValue($tokenIterator);
+ if ('' !== $domainToken) {
+ $domain = $domainToken;
+ }
+
+ break;
+ } else {
+ break;
+ }
+ }
+
+ if ($message) {
+ $catalog->set($message, $this->prefix.$message, $domain);
+ $metadata = $catalog->getMetadata($message, $domain) ?? [];
+ $normalizedFilename = preg_replace('{[\\\\/]+}', '/', $filename);
+ $metadata['sources'][] = $normalizedFilename.':'.$tokens[$key][2];
+ $catalog->setMetadata($message, $metadata, $domain);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * @return bool
+ *
+ * @throws \InvalidArgumentException
+ */
+ protected function canBeExtracted(string $file)
+ {
+ return $this->isFile($file) && 'php' === pathinfo($file, \PATHINFO_EXTENSION);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function extractFromDirectory($directory)
+ {
+ $finder = new Finder();
+
+ return $finder->files()->name('*.php')->in($directory);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpStringTokenParser.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpStringTokenParser.php
new file mode 100644
index 0000000..1d82caf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpStringTokenParser.php
@@ -0,0 +1,142 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+/*
+ * The following is derived from code at http://github.com/nikic/PHP-Parser
+ *
+ * Copyright (c) 2011 by Nikita Popov
+ *
+ * Some rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * * The names of the contributors may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+class PhpStringTokenParser
+{
+ protected static $replacements = [
+ '\\' => '\\',
+ '$' => '$',
+ 'n' => "\n",
+ 'r' => "\r",
+ 't' => "\t",
+ 'f' => "\f",
+ 'v' => "\v",
+ 'e' => "\x1B",
+ ];
+
+ /**
+ * Parses a string token.
+ *
+ * @param string $str String token content
+ *
+ * @return string The parsed string
+ */
+ public static function parse(string $str)
+ {
+ $bLength = 0;
+ if ('b' === $str[0]) {
+ $bLength = 1;
+ }
+
+ if ('\'' === $str[$bLength]) {
+ return str_replace(
+ ['\\\\', '\\\''],
+ ['\\', '\''],
+ substr($str, $bLength + 1, -1)
+ );
+ } else {
+ return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"');
+ }
+ }
+
+ /**
+ * Parses escape sequences in strings (all string types apart from single quoted).
+ *
+ * @param string $str String without quotes
+ * @param string|null $quote Quote type
+ *
+ * @return string String with escape sequences parsed
+ */
+ public static function parseEscapeSequences(string $str, string $quote = null)
+ {
+ if (null !== $quote) {
+ $str = str_replace('\\'.$quote, $quote, $str);
+ }
+
+ return preg_replace_callback(
+ '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~',
+ [__CLASS__, 'parseCallback'],
+ $str
+ );
+ }
+
+ private static function parseCallback(array $matches): string
+ {
+ $str = $matches[1];
+
+ if (isset(self::$replacements[$str])) {
+ return self::$replacements[$str];
+ } elseif ('x' === $str[0] || 'X' === $str[0]) {
+ return \chr(hexdec($str));
+ } else {
+ return \chr(octdec($str));
+ }
+ }
+
+ /**
+ * Parses a constant doc string.
+ *
+ * @param string $startToken Doc string start token content (<<<SMTHG)
+ * @param string $str String token content
+ *
+ * @return string Parsed string
+ */
+ public static function parseDocString(string $startToken, string $str)
+ {
+ // strip last newline (thanks tokenizer for sticking it into the string!)
+ $str = preg_replace('~(\r\n|\n|\r)$~', '', $str);
+
+ // nowdoc string
+ if (str_contains($startToken, '\'')) {
+ return $str;
+ }
+
+ return self::parseEscapeSequences($str, null);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatter.php
new file mode 100644
index 0000000..f7f1c36
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatter.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\LogicException;
+
+/**
+ * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class IntlFormatter implements IntlFormatterInterface
+{
+ private $hasMessageFormatter;
+ private $cache = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatIntl(string $message, string $locale, array $parameters = []): string
+ {
+ // MessageFormatter constructor throws an exception if the message is empty
+ if ('' === $message) {
+ return '';
+ }
+
+ if (!$formatter = $this->cache[$locale][$message] ?? null) {
+ if (!($this->hasMessageFormatter ?? $this->hasMessageFormatter = class_exists(\MessageFormatter::class))) {
+ throw new LogicException('Cannot parse message translation: please install the "intl" PHP extension or the "symfony/polyfill-intl-messageformatter" package.');
+ }
+ try {
+ $this->cache[$locale][$message] = $formatter = new \MessageFormatter($locale, $message);
+ } catch (\IntlException $e) {
+ throw new InvalidArgumentException(sprintf('Invalid message format (error #%d): ', intl_get_error_code()).intl_get_error_message(), 0, $e);
+ }
+ }
+
+ foreach ($parameters as $key => $value) {
+ if (\in_array($key[0] ?? null, ['%', '{'], true)) {
+ unset($parameters[$key]);
+ $parameters[trim($key, '%{ }')] = $value;
+ }
+ }
+
+ if (false === $message = $formatter->format($parameters)) {
+ throw new InvalidArgumentException(sprintf('Unable to format message (error #%s): ', $formatter->getErrorCode()).$formatter->getErrorMessage());
+ }
+
+ return $message;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatterInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatterInterface.php
new file mode 100644
index 0000000..02fc6ac
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatterInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+/**
+ * Formats ICU message patterns.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+interface IntlFormatterInterface
+{
+ /**
+ * Formats a localized message using rules defined by ICU MessageFormat.
+ *
+ * @see http://icu-project.org/apiref/icu4c/classMessageFormat.html#details
+ */
+ public function formatIntl(string $message, string $locale, array $parameters = []): string;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatter.php
new file mode 100644
index 0000000..0407964
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatter.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+use Symfony\Component\Translation\IdentityTranslator;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(IntlFormatter::class);
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class MessageFormatter implements MessageFormatterInterface, IntlFormatterInterface
+{
+ private $translator;
+ private $intlFormatter;
+
+ /**
+ * @param TranslatorInterface|null $translator An identity translator to use as selector for pluralization
+ */
+ public function __construct(TranslatorInterface $translator = null, IntlFormatterInterface $intlFormatter = null)
+ {
+ $this->translator = $translator ?? new IdentityTranslator();
+ $this->intlFormatter = $intlFormatter ?? new IntlFormatter();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function format(string $message, string $locale, array $parameters = [])
+ {
+ if ($this->translator instanceof TranslatorInterface) {
+ return $this->translator->trans($message, $parameters, null, $locale);
+ }
+
+ return strtr($message, $parameters);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatIntl(string $message, string $locale, array $parameters = []): string
+ {
+ return $this->intlFormatter->formatIntl($message, $locale, $parameters);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatterInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatterInterface.php
new file mode 100644
index 0000000..b85dbfd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatterInterface.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+/**
+ * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+interface MessageFormatterInterface
+{
+ /**
+ * Formats a localized message pattern with given arguments.
+ *
+ * @param string $message The message (may also be an object that can be cast to string)
+ * @param string $locale The message locale
+ * @param array $parameters An array of parameters for the message
+ *
+ * @return string
+ */
+ public function format(string $message, string $locale, array $parameters = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/IdentityTranslator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/IdentityTranslator.php
new file mode 100644
index 0000000..46875ed
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/IdentityTranslator.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Contracts\Translation\LocaleAwareInterface;
+use Symfony\Contracts\Translation\TranslatorInterface;
+use Symfony\Contracts\Translation\TranslatorTrait;
+
+/**
+ * IdentityTranslator does not translate anything.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class IdentityTranslator implements TranslatorInterface, LocaleAwareInterface
+{
+ use TranslatorTrait;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LICENSE
new file mode 100644
index 0000000..9ff2d0d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2021 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/ArrayLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/ArrayLoader.php
new file mode 100644
index 0000000..0758da8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/ArrayLoader.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * ArrayLoader loads translations from a PHP array.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ArrayLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ $resource = $this->flatten($resource);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($resource, $domain);
+
+ return $catalogue;
+ }
+
+ /**
+ * Flattens an nested array of translations.
+ *
+ * The scheme used is:
+ * 'key' => ['key2' => ['key3' => 'value']]
+ * Becomes:
+ * 'key.key2.key3' => 'value'
+ */
+ private function flatten(array $messages): array
+ {
+ $result = [];
+ foreach ($messages as $key => $value) {
+ if (\is_array($value)) {
+ foreach ($this->flatten($value) as $k => $v) {
+ $result[$key.'.'.$k] = $v;
+ }
+ } else {
+ $result[$key] = $value;
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php
new file mode 100644
index 0000000..8d5d4db
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+
+/**
+ * CsvFileLoader loads translations from CSV files.
+ *
+ * @author Saša Stamenković <umpirsky@gmail.com>
+ */
+class CsvFileLoader extends FileLoader
+{
+ private $delimiter = ';';
+ private $enclosure = '"';
+ private $escape = '\\';
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $messages = [];
+
+ try {
+ $file = new \SplFileObject($resource, 'rb');
+ } catch (\RuntimeException $e) {
+ throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e);
+ }
+
+ $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY);
+ $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);
+
+ foreach ($file as $data) {
+ if (false === $data) {
+ continue;
+ }
+
+ if ('#' !== substr($data[0], 0, 1) && isset($data[1]) && 2 === \count($data)) {
+ $messages[$data[0]] = $data[1];
+ }
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Sets the delimiter, enclosure, and escape character for CSV.
+ */
+ public function setCsvControl(string $delimiter = ';', string $enclosure = '"', string $escape = '\\')
+ {
+ $this->delimiter = $delimiter;
+ $this->enclosure = $enclosure;
+ $this->escape = $escape;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php
new file mode 100644
index 0000000..4725ea6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+abstract class FileLoader extends ArrayLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ $messages = $this->loadResource($resource);
+
+ // empty resource
+ if (null === $messages) {
+ $messages = [];
+ }
+
+ // not an array
+ if (!\is_array($messages)) {
+ throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource));
+ }
+
+ $catalogue = parent::load($messages, $locale, $domain);
+
+ if (class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ /**
+ * @return array
+ *
+ * @throws InvalidResourceException if stream content has an invalid format
+ */
+ abstract protected function loadResource(string $resource);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuDatFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuDatFileLoader.php
new file mode 100644
index 0000000..2a1aecc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuDatFileLoader.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IcuResFileLoader loads translations from a resource bundle.
+ *
+ * @author stealth35
+ */
+class IcuDatFileLoader extends IcuResFileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!stream_is_local($resource.'.dat')) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource.'.dat')) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $rb = new \ResourceBundle($locale, $resource);
+ } catch (\Exception $e) {
+ $rb = null;
+ }
+
+ if (!$rb) {
+ throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource));
+ } elseif (intl_is_failure($rb->getErrorCode())) {
+ throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
+ }
+
+ $messages = $this->flatten($rb);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($messages, $domain);
+
+ if (class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource.'.dat'));
+ }
+
+ return $catalogue;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuResFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuResFileLoader.php
new file mode 100644
index 0000000..64bbd3e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuResFileLoader.php
@@ -0,0 +1,91 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\DirectoryResource;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IcuResFileLoader loads translations from a resource bundle.
+ *
+ * @author stealth35
+ */
+class IcuResFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!is_dir($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $rb = new \ResourceBundle($locale, $resource);
+ } catch (\Exception $e) {
+ $rb = null;
+ }
+
+ if (!$rb) {
+ throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource));
+ } elseif (intl_is_failure($rb->getErrorCode())) {
+ throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
+ }
+
+ $messages = $this->flatten($rb);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($messages, $domain);
+
+ if (class_exists(DirectoryResource::class)) {
+ $catalogue->addResource(new DirectoryResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ /**
+ * Flattens an ResourceBundle.
+ *
+ * The scheme used is:
+ * key { key2 { key3 { "value" } } }
+ * Becomes:
+ * 'key.key2.key3' => 'value'
+ *
+ * This function takes an array by reference and will modify it
+ *
+ * @param \ResourceBundle $rb The ResourceBundle that will be flattened
+ * @param array $messages Used internally for recursive calls
+ * @param string $path Current path being parsed, used internally for recursive calls
+ *
+ * @return array the flattened ResourceBundle
+ */
+ protected function flatten(\ResourceBundle $rb, array &$messages = [], string $path = null)
+ {
+ foreach ($rb as $key => $value) {
+ $nodePath = $path ? $path.'.'.$key : $key;
+ if ($value instanceof \ResourceBundle) {
+ $this->flatten($value, $messages, $nodePath);
+ } else {
+ $messages[$nodePath] = $value;
+ }
+ }
+
+ return $messages;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php
new file mode 100644
index 0000000..7398f77
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * IniFileLoader loads translations from an ini file.
+ *
+ * @author stealth35
+ */
+class IniFileLoader extends FileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ return parse_ini_file($resource, true);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php
new file mode 100644
index 0000000..5aefba0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+
+/**
+ * JsonFileLoader loads translations from an json file.
+ *
+ * @author singles
+ */
+class JsonFileLoader extends FileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $messages = [];
+ if ($data = file_get_contents($resource)) {
+ $messages = json_decode($data, true);
+
+ if (0 < $errorCode = json_last_error()) {
+ throw new InvalidResourceException('Error parsing JSON: '.$this->getJSONErrorMessage($errorCode));
+ }
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Translates JSON_ERROR_* constant into meaningful message.
+ */
+ private function getJSONErrorMessage(int $errorCode): string
+ {
+ switch ($errorCode) {
+ case \JSON_ERROR_DEPTH:
+ return 'Maximum stack depth exceeded';
+ case \JSON_ERROR_STATE_MISMATCH:
+ return 'Underflow or the modes mismatch';
+ case \JSON_ERROR_CTRL_CHAR:
+ return 'Unexpected control character found';
+ case \JSON_ERROR_SYNTAX:
+ return 'Syntax error, malformed JSON';
+ case \JSON_ERROR_UTF8:
+ return 'Malformed UTF-8 characters, possibly incorrectly encoded';
+ default:
+ return 'Unknown error';
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/LoaderInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/LoaderInterface.php
new file mode 100644
index 0000000..2073f2b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/LoaderInterface.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * LoaderInterface is the interface implemented by all translation loaders.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface LoaderInterface
+{
+ /**
+ * Loads a locale.
+ *
+ * @param mixed $resource A resource
+ * @param string $locale A locale
+ * @param string $domain The domain
+ *
+ * @return MessageCatalogue A MessageCatalogue instance
+ *
+ * @throws NotFoundResourceException when the resource cannot be found
+ * @throws InvalidResourceException when the resource cannot be loaded
+ */
+ public function load($resource, string $locale, string $domain = 'messages');
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php
new file mode 100644
index 0000000..0ff6549
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php
@@ -0,0 +1,140 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+
+/**
+ * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
+ */
+class MoFileLoader extends FileLoader
+{
+ /**
+ * Magic used for validating the format of an MO file as well as
+ * detecting if the machine used to create that file was little endian.
+ */
+ public const MO_LITTLE_ENDIAN_MAGIC = 0x950412de;
+
+ /**
+ * Magic used for validating the format of an MO file as well as
+ * detecting if the machine used to create that file was big endian.
+ */
+ public const MO_BIG_ENDIAN_MAGIC = 0xde120495;
+
+ /**
+ * The size of the header of an MO file in bytes.
+ */
+ public const MO_HEADER_SIZE = 28;
+
+ /**
+ * Parses machine object (MO) format, independent of the machine's endian it
+ * was created on. Both 32bit and 64bit systems are supported.
+ *
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $stream = fopen($resource, 'r');
+
+ $stat = fstat($stream);
+
+ if ($stat['size'] < self::MO_HEADER_SIZE) {
+ throw new InvalidResourceException('MO stream content has an invalid format.');
+ }
+ $magic = unpack('V1', fread($stream, 4));
+ $magic = hexdec(substr(dechex(current($magic)), -8));
+
+ if (self::MO_LITTLE_ENDIAN_MAGIC == $magic) {
+ $isBigEndian = false;
+ } elseif (self::MO_BIG_ENDIAN_MAGIC == $magic) {
+ $isBigEndian = true;
+ } else {
+ throw new InvalidResourceException('MO stream content has an invalid format.');
+ }
+
+ // formatRevision
+ $this->readLong($stream, $isBigEndian);
+ $count = $this->readLong($stream, $isBigEndian);
+ $offsetId = $this->readLong($stream, $isBigEndian);
+ $offsetTranslated = $this->readLong($stream, $isBigEndian);
+ // sizeHashes
+ $this->readLong($stream, $isBigEndian);
+ // offsetHashes
+ $this->readLong($stream, $isBigEndian);
+
+ $messages = [];
+
+ for ($i = 0; $i < $count; ++$i) {
+ $pluralId = null;
+ $translated = null;
+
+ fseek($stream, $offsetId + $i * 8);
+
+ $length = $this->readLong($stream, $isBigEndian);
+ $offset = $this->readLong($stream, $isBigEndian);
+
+ if ($length < 1) {
+ continue;
+ }
+
+ fseek($stream, $offset);
+ $singularId = fread($stream, $length);
+
+ if (str_contains($singularId, "\000")) {
+ [$singularId, $pluralId] = explode("\000", $singularId);
+ }
+
+ fseek($stream, $offsetTranslated + $i * 8);
+ $length = $this->readLong($stream, $isBigEndian);
+ $offset = $this->readLong($stream, $isBigEndian);
+
+ if ($length < 1) {
+ continue;
+ }
+
+ fseek($stream, $offset);
+ $translated = fread($stream, $length);
+
+ if (str_contains($translated, "\000")) {
+ $translated = explode("\000", $translated);
+ }
+
+ $ids = ['singular' => $singularId, 'plural' => $pluralId];
+ $item = compact('ids', 'translated');
+
+ if (!empty($item['ids']['singular'])) {
+ $id = $item['ids']['singular'];
+ if (isset($item['ids']['plural'])) {
+ $id .= '|'.$item['ids']['plural'];
+ }
+ $messages[$id] = stripcslashes(implode('|', (array) $item['translated']));
+ }
+ }
+
+ fclose($stream);
+
+ return array_filter($messages);
+ }
+
+ /**
+ * Reads an unsigned long from stream respecting endianness.
+ *
+ * @param resource $stream
+ */
+ private function readLong($stream, bool $isBigEndian): int
+ {
+ $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4));
+ $result = current($result);
+
+ return (int) substr($result, -8);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php
new file mode 100644
index 0000000..85f1090
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * PhpFileLoader loads translations from PHP files returning an array of translations.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class PhpFileLoader extends FileLoader
+{
+ private static $cache = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) {
+ self::$cache = null;
+ }
+
+ if (null === self::$cache) {
+ return require $resource;
+ }
+
+ if (isset(self::$cache[$resource])) {
+ return self::$cache[$resource];
+ }
+
+ return self::$cache[$resource] = require $resource;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php
new file mode 100644
index 0000000..ee143e2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php
@@ -0,0 +1,149 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * @copyright Copyright (c) 2010, Union of RAD https://github.com/UnionOfRAD/lithium
+ * @copyright Copyright (c) 2012, Clemens Tolboom
+ */
+class PoFileLoader extends FileLoader
+{
+ /**
+ * Parses portable object (PO) format.
+ *
+ * From https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files
+ * we should be able to parse files having:
+ *
+ * white-space
+ * # translator-comments
+ * #. extracted-comments
+ * #: reference...
+ * #, flag...
+ * #| msgid previous-untranslated-string
+ * msgid untranslated-string
+ * msgstr translated-string
+ *
+ * extra or different lines are:
+ *
+ * #| msgctxt previous-context
+ * #| msgid previous-untranslated-string
+ * msgctxt context
+ *
+ * #| msgid previous-untranslated-string-singular
+ * #| msgid_plural previous-untranslated-string-plural
+ * msgid untranslated-string-singular
+ * msgid_plural untranslated-string-plural
+ * msgstr[0] translated-string-case-0
+ * ...
+ * msgstr[N] translated-string-case-n
+ *
+ * The definition states:
+ * - white-space and comments are optional.
+ * - msgid "" that an empty singleline defines a header.
+ *
+ * This parser sacrifices some features of the reference implementation the
+ * differences to that implementation are as follows.
+ * - No support for comments spanning multiple lines.
+ * - Translator and extracted comments are treated as being the same type.
+ * - Message IDs are allowed to have other encodings as just US-ASCII.
+ *
+ * Items with an empty id are ignored.
+ *
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $stream = fopen($resource, 'r');
+
+ $defaults = [
+ 'ids' => [],
+ 'translated' => null,
+ ];
+
+ $messages = [];
+ $item = $defaults;
+ $flags = [];
+
+ while ($line = fgets($stream)) {
+ $line = trim($line);
+
+ if ('' === $line) {
+ // Whitespace indicated current item is done
+ if (!\in_array('fuzzy', $flags)) {
+ $this->addMessage($messages, $item);
+ }
+ $item = $defaults;
+ $flags = [];
+ } elseif ('#,' === substr($line, 0, 2)) {
+ $flags = array_map('trim', explode(',', substr($line, 2)));
+ } elseif ('msgid "' === substr($line, 0, 7)) {
+ // We start a new msg so save previous
+ // TODO: this fails when comments or contexts are added
+ $this->addMessage($messages, $item);
+ $item = $defaults;
+ $item['ids']['singular'] = substr($line, 7, -1);
+ } elseif ('msgstr "' === substr($line, 0, 8)) {
+ $item['translated'] = substr($line, 8, -1);
+ } elseif ('"' === $line[0]) {
+ $continues = isset($item['translated']) ? 'translated' : 'ids';
+
+ if (\is_array($item[$continues])) {
+ end($item[$continues]);
+ $item[$continues][key($item[$continues])] .= substr($line, 1, -1);
+ } else {
+ $item[$continues] .= substr($line, 1, -1);
+ }
+ } elseif ('msgid_plural "' === substr($line, 0, 14)) {
+ $item['ids']['plural'] = substr($line, 14, -1);
+ } elseif ('msgstr[' === substr($line, 0, 7)) {
+ $size = strpos($line, ']');
+ $item['translated'][(int) substr($line, 7, 1)] = substr($line, $size + 3, -1);
+ }
+ }
+ // save last item
+ if (!\in_array('fuzzy', $flags)) {
+ $this->addMessage($messages, $item);
+ }
+ fclose($stream);
+
+ return $messages;
+ }
+
+ /**
+ * Save a translation item to the messages.
+ *
+ * A .po file could contain by error missing plural indexes. We need to
+ * fix these before saving them.
+ */
+ private function addMessage(array &$messages, array $item)
+ {
+ if (!empty($item['ids']['singular'])) {
+ $id = stripcslashes($item['ids']['singular']);
+ if (isset($item['ids']['plural'])) {
+ $id .= '|'.stripcslashes($item['ids']['plural']);
+ }
+
+ $translated = (array) $item['translated'];
+ // PO are by definition indexed so sort by index.
+ ksort($translated);
+ // Make sure every index is filled.
+ end($translated);
+ $count = key($translated);
+ // Fill missing spots with '-'.
+ $empties = array_fill(0, $count + 1, '-');
+ $translated += $empties;
+ ksort($translated);
+
+ $messages[$id] = stripcslashes(implode('|', $translated));
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/QtFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/QtFileLoader.php
new file mode 100644
index 0000000..9cf2fe9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/QtFileLoader.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Util\XmlUtils;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * QtFileLoader loads translations from QT Translations XML files.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class QtFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!class_exists(XmlUtils::class)) {
+ throw new RuntimeException('Loading translations from the QT format requires the Symfony Config component.');
+ }
+
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $dom = XmlUtils::loadFile($resource);
+ } catch (\InvalidArgumentException $e) {
+ throw new InvalidResourceException(sprintf('Unable to load "%s".', $resource), $e->getCode(), $e);
+ }
+
+ $internalErrors = libxml_use_internal_errors(true);
+ libxml_clear_errors();
+
+ $xpath = new \DOMXPath($dom);
+ $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]');
+
+ $catalogue = new MessageCatalogue($locale);
+ if (1 == $nodes->length) {
+ $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message');
+ foreach ($translations as $translation) {
+ $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue;
+
+ if (!empty($translationValue)) {
+ $catalogue->set(
+ (string) $translation->getElementsByTagName('source')->item(0)->nodeValue,
+ $translationValue,
+ $domain
+ );
+ }
+ $translation = $translation->nextSibling;
+ }
+
+ if (class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+ }
+
+ libxml_use_internal_errors($internalErrors);
+
+ return $catalogue;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php
new file mode 100644
index 0000000..35ad33e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php
@@ -0,0 +1,232 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Util\Exception\InvalidXmlException;
+use Symfony\Component\Config\Util\Exception\XmlParsingException;
+use Symfony\Component\Config\Util\XmlUtils;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Util\XliffUtils;
+
+/**
+ * XliffFileLoader loads translations from XLIFF files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class XliffFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!class_exists(XmlUtils::class)) {
+ throw new RuntimeException('Loading translations from the Xliff format requires the Symfony Config component.');
+ }
+
+ if (!$this->isXmlString($resource)) {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ if (!is_file($resource)) {
+ throw new InvalidResourceException(sprintf('This is neither a file nor an XLIFF string "%s".', $resource));
+ }
+ }
+
+ try {
+ if ($this->isXmlString($resource)) {
+ $dom = XmlUtils::parse($resource);
+ } else {
+ $dom = XmlUtils::loadFile($resource);
+ }
+ } catch (\InvalidArgumentException | XmlParsingException | InvalidXmlException $e) {
+ throw new InvalidResourceException(sprintf('Unable to load "%s": ', $resource).$e->getMessage(), $e->getCode(), $e);
+ }
+
+ if ($errors = XliffUtils::validateSchema($dom)) {
+ throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: ', $resource).XliffUtils::getErrorsAsString($errors));
+ }
+
+ $catalogue = new MessageCatalogue($locale);
+ $this->extract($dom, $catalogue, $domain);
+
+ if (is_file($resource) && class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ private function extract(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
+ {
+ $xliffVersion = XliffUtils::getVersionNumber($dom);
+
+ if ('1.2' === $xliffVersion) {
+ $this->extractXliff1($dom, $catalogue, $domain);
+ }
+
+ if ('2.0' === $xliffVersion) {
+ $this->extractXliff2($dom, $catalogue, $domain);
+ }
+ }
+
+ /**
+ * Extract messages and metadata from DOMDocument into a MessageCatalogue.
+ */
+ private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
+ {
+ $xml = simplexml_import_dom($dom);
+ $encoding = $dom->encoding ? strtoupper($dom->encoding) : null;
+
+ $namespace = 'urn:oasis:names:tc:xliff:document:1.2';
+ $xml->registerXPathNamespace('xliff', $namespace);
+
+ foreach ($xml->xpath('//xliff:file') as $file) {
+ $fileAttributes = $file->attributes();
+
+ $file->registerXPathNamespace('xliff', $namespace);
+
+ foreach ($file->xpath('.//xliff:trans-unit') as $translation) {
+ $attributes = $translation->attributes();
+
+ if (!(isset($attributes['resname']) || isset($translation->source))) {
+ continue;
+ }
+
+ $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source;
+ // If the xlf file has another encoding specified, try to convert it because
+ // simple_xml will always return utf-8 encoded values
+ $target = $this->utf8ToCharset((string) ($translation->target ?? $translation->source), $encoding);
+
+ $catalogue->set((string) $source, $target, $domain);
+
+ $metadata = [
+ 'source' => (string) $translation->source,
+ 'file' => [
+ 'original' => (string) $fileAttributes['original'],
+ ],
+ ];
+ if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) {
+ $metadata['notes'] = $notes;
+ }
+
+ if (isset($translation->target) && $translation->target->attributes()) {
+ $metadata['target-attributes'] = [];
+ foreach ($translation->target->attributes() as $key => $value) {
+ $metadata['target-attributes'][$key] = (string) $value;
+ }
+ }
+
+ if (isset($attributes['id'])) {
+ $metadata['id'] = (string) $attributes['id'];
+ }
+
+ $catalogue->setMetadata((string) $source, $metadata, $domain);
+ }
+ }
+ }
+
+ private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
+ {
+ $xml = simplexml_import_dom($dom);
+ $encoding = $dom->encoding ? strtoupper($dom->encoding) : null;
+
+ $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0');
+
+ foreach ($xml->xpath('//xliff:unit') as $unit) {
+ foreach ($unit->segment as $segment) {
+ $attributes = $unit->attributes();
+ $source = $attributes['name'] ?? $segment->source;
+
+ // If the xlf file has another encoding specified, try to convert it because
+ // simple_xml will always return utf-8 encoded values
+ $target = $this->utf8ToCharset((string) ($segment->target ?? $segment->source), $encoding);
+
+ $catalogue->set((string) $source, $target, $domain);
+
+ $metadata = [];
+ if (isset($segment->target) && $segment->target->attributes()) {
+ $metadata['target-attributes'] = [];
+ foreach ($segment->target->attributes() as $key => $value) {
+ $metadata['target-attributes'][$key] = (string) $value;
+ }
+ }
+
+ if (isset($unit->notes)) {
+ $metadata['notes'] = [];
+ foreach ($unit->notes->note as $noteNode) {
+ $note = [];
+ foreach ($noteNode->attributes() as $key => $value) {
+ $note[$key] = (string) $value;
+ }
+ $note['content'] = (string) $noteNode;
+ $metadata['notes'][] = $note;
+ }
+ }
+
+ $catalogue->setMetadata((string) $source, $metadata, $domain);
+ }
+ }
+ }
+
+ /**
+ * Convert a UTF8 string to the specified encoding.
+ */
+ private function utf8ToCharset(string $content, string $encoding = null): string
+ {
+ if ('UTF-8' !== $encoding && !empty($encoding)) {
+ return mb_convert_encoding($content, $encoding, 'UTF-8');
+ }
+
+ return $content;
+ }
+
+ private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, string $encoding = null): array
+ {
+ $notes = [];
+
+ if (null === $noteElement) {
+ return $notes;
+ }
+
+ /** @var \SimpleXMLElement $xmlNote */
+ foreach ($noteElement as $xmlNote) {
+ $noteAttributes = $xmlNote->attributes();
+ $note = ['content' => $this->utf8ToCharset((string) $xmlNote, $encoding)];
+ if (isset($noteAttributes['priority'])) {
+ $note['priority'] = (int) $noteAttributes['priority'];
+ }
+
+ if (isset($noteAttributes['from'])) {
+ $note['from'] = (string) $noteAttributes['from'];
+ }
+
+ $notes[] = $note;
+ }
+
+ return $notes;
+ }
+
+ private function isXmlString(string $resource): bool
+ {
+ return 0 === strpos($resource, '<?xml');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php
new file mode 100644
index 0000000..8588e18
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\LogicException;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Parser as YamlParser;
+use Symfony\Component\Yaml\Yaml;
+
+/**
+ * YamlFileLoader loads translations from Yaml files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class YamlFileLoader extends FileLoader
+{
+ private $yamlParser;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ if (null === $this->yamlParser) {
+ if (!class_exists(\Symfony\Component\Yaml\Parser::class)) {
+ throw new LogicException('Loading translations from the YAML format requires the Symfony Yaml component.');
+ }
+
+ $this->yamlParser = new YamlParser();
+ }
+
+ try {
+ $messages = $this->yamlParser->parseFile($resource, Yaml::PARSE_CONSTANT);
+ } catch (ParseException $e) {
+ throw new InvalidResourceException(sprintf('The file "%s" does not contain valid YAML: ', $resource).$e->getMessage(), 0, $e);
+ }
+
+ if (null !== $messages && !\is_array($messages)) {
+ throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource));
+ }
+
+ return $messages ?: [];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LoggingTranslator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LoggingTranslator.php
new file mode 100644
index 0000000..bb93435
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LoggingTranslator.php
@@ -0,0 +1,135 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Contracts\Translation\LocaleAwareInterface;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface
+{
+ /**
+ * @var TranslatorInterface|TranslatorBagInterface
+ */
+ private $translator;
+
+ private $logger;
+
+ /**
+ * @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
+ */
+ public function __construct(TranslatorInterface $translator, LoggerInterface $logger)
+ {
+ if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) {
+ throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator)));
+ }
+
+ $this->translator = $translator;
+ $this->logger = $logger;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null)
+ {
+ $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale);
+ $this->log($id, $domain, $locale);
+
+ return $trans;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale(string $locale)
+ {
+ $prev = $this->translator->getLocale();
+ $this->translator->setLocale($locale);
+ if ($prev === $locale) {
+ return;
+ }
+
+ $this->logger->debug(sprintf('The locale of the translator has changed from "%s" to "%s".', $prev, $locale));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->translator->getLocale();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue(string $locale = null)
+ {
+ return $this->translator->getCatalogue($locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogues(): array
+ {
+ return $this->translator->getCatalogues();
+ }
+
+ /**
+ * Gets the fallback locales.
+ *
+ * @return array The fallback locales
+ */
+ public function getFallbackLocales()
+ {
+ if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) {
+ return $this->translator->getFallbackLocales();
+ }
+
+ return [];
+ }
+
+ /**
+ * Passes through all unknown calls onto the translator object.
+ */
+ public function __call(string $method, array $args)
+ {
+ return $this->translator->{$method}(...$args);
+ }
+
+ /**
+ * Logs for missing translations.
+ */
+ private function log(string $id, ?string $domain, ?string $locale)
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $catalogue = $this->translator->getCatalogue($locale);
+ if ($catalogue->defines($id, $domain)) {
+ return;
+ }
+
+ if ($catalogue->has($id, $domain)) {
+ $this->logger->debug('Translation use fallback catalogue.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]);
+ } else {
+ $this->logger->warning('Translation not found.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogue.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogue.php
new file mode 100644
index 0000000..ff49b5a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogue.php
@@ -0,0 +1,314 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Config\Resource\ResourceInterface;
+use Symfony\Component\Translation\Exception\LogicException;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface
+{
+ private $messages = [];
+ private $metadata = [];
+ private $resources = [];
+ private $locale;
+ private $fallbackCatalogue;
+ private $parent;
+
+ /**
+ * @param array $messages An array of messages classified by domain
+ */
+ public function __construct(string $locale, array $messages = [])
+ {
+ $this->locale = $locale;
+ $this->messages = $messages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDomains()
+ {
+ $domains = [];
+
+ foreach ($this->messages as $domain => $messages) {
+ if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
+ $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX));
+ }
+ $domains[$domain] = $domain;
+ }
+
+ return array_values($domains);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function all(string $domain = null)
+ {
+ if (null !== $domain) {
+ // skip messages merge if intl-icu requested explicitly
+ if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
+ return $this->messages[$domain] ?? [];
+ }
+
+ return ($this->messages[$domain.self::INTL_DOMAIN_SUFFIX] ?? []) + ($this->messages[$domain] ?? []);
+ }
+
+ $allMessages = [];
+
+ foreach ($this->messages as $domain => $messages) {
+ if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
+ $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX));
+ $allMessages[$domain] = $messages + ($allMessages[$domain] ?? []);
+ } else {
+ $allMessages[$domain] = ($allMessages[$domain] ?? []) + $messages;
+ }
+ }
+
+ return $allMessages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set(string $id, string $translation, string $domain = 'messages')
+ {
+ $this->add([$id => $translation], $domain);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has(string $id, string $domain = 'messages')
+ {
+ if (isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) {
+ return true;
+ }
+
+ if (null !== $this->fallbackCatalogue) {
+ return $this->fallbackCatalogue->has($id, $domain);
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function defines(string $id, string $domain = 'messages')
+ {
+ return isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $id, string $domain = 'messages')
+ {
+ if (isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) {
+ return $this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id];
+ }
+
+ if (isset($this->messages[$domain][$id])) {
+ return $this->messages[$domain][$id];
+ }
+
+ if (null !== $this->fallbackCatalogue) {
+ return $this->fallbackCatalogue->get($id, $domain);
+ }
+
+ return $id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function replace(array $messages, string $domain = 'messages')
+ {
+ unset($this->messages[$domain], $this->messages[$domain.self::INTL_DOMAIN_SUFFIX]);
+
+ $this->add($messages, $domain);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add(array $messages, string $domain = 'messages')
+ {
+ if (!isset($this->messages[$domain])) {
+ $this->messages[$domain] = [];
+ }
+ $intlDomain = $domain;
+ if (!str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
+ $intlDomain .= self::INTL_DOMAIN_SUFFIX;
+ }
+ foreach ($messages as $id => $message) {
+ if (isset($this->messages[$intlDomain]) && \array_key_exists($id, $this->messages[$intlDomain])) {
+ $this->messages[$intlDomain][$id] = $message;
+ } else {
+ $this->messages[$domain][$id] = $message;
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addCatalogue(MessageCatalogueInterface $catalogue)
+ {
+ if ($catalogue->getLocale() !== $this->locale) {
+ throw new LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s".', $catalogue->getLocale(), $this->locale));
+ }
+
+ foreach ($catalogue->all() as $domain => $messages) {
+ if ($intlMessages = $catalogue->all($domain.self::INTL_DOMAIN_SUFFIX)) {
+ $this->add($intlMessages, $domain.self::INTL_DOMAIN_SUFFIX);
+ $messages = array_diff_key($messages, $intlMessages);
+ }
+ $this->add($messages, $domain);
+ }
+
+ foreach ($catalogue->getResources() as $resource) {
+ $this->addResource($resource);
+ }
+
+ if ($catalogue instanceof MetadataAwareInterface) {
+ $metadata = $catalogue->getMetadata('', '');
+ $this->addMetadata($metadata);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue)
+ {
+ // detect circular references
+ $c = $catalogue;
+ while ($c = $c->getFallbackCatalogue()) {
+ if ($c->getLocale() === $this->getLocale()) {
+ throw new LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
+ }
+ }
+
+ $c = $this;
+ do {
+ if ($c->getLocale() === $catalogue->getLocale()) {
+ throw new LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
+ }
+
+ foreach ($catalogue->getResources() as $resource) {
+ $c->addResource($resource);
+ }
+ } while ($c = $c->parent);
+
+ $catalogue->parent = $this;
+ $this->fallbackCatalogue = $catalogue;
+
+ foreach ($catalogue->getResources() as $resource) {
+ $this->addResource($resource);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFallbackCatalogue()
+ {
+ return $this->fallbackCatalogue;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getResources()
+ {
+ return array_values($this->resources);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addResource(ResourceInterface $resource)
+ {
+ $this->resources[$resource->__toString()] = $resource;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadata(string $key = '', string $domain = 'messages')
+ {
+ if ('' == $domain) {
+ return $this->metadata;
+ }
+
+ if (isset($this->metadata[$domain])) {
+ if ('' == $key) {
+ return $this->metadata[$domain];
+ }
+
+ if (isset($this->metadata[$domain][$key])) {
+ return $this->metadata[$domain][$key];
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMetadata(string $key, $value, string $domain = 'messages')
+ {
+ $this->metadata[$domain][$key] = $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteMetadata(string $key = '', string $domain = 'messages')
+ {
+ if ('' == $domain) {
+ $this->metadata = [];
+ } elseif ('' == $key) {
+ unset($this->metadata[$domain]);
+ } else {
+ unset($this->metadata[$domain][$key]);
+ }
+ }
+
+ /**
+ * Adds current values with the new values.
+ *
+ * @param array $values Values to add
+ */
+ private function addMetadata(array $values)
+ {
+ foreach ($values as $domain => $keys) {
+ foreach ($keys as $key => $value) {
+ $this->setMetadata($key, $value, $domain);
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogueInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogueInterface.php
new file mode 100644
index 0000000..5d83bd8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogueInterface.php
@@ -0,0 +1,138 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Config\Resource\ResourceInterface;
+
+/**
+ * MessageCatalogueInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface MessageCatalogueInterface
+{
+ public const INTL_DOMAIN_SUFFIX = '+intl-icu';
+
+ /**
+ * Gets the catalogue locale.
+ *
+ * @return string The locale
+ */
+ public function getLocale();
+
+ /**
+ * Gets the domains.
+ *
+ * @return array An array of domains
+ */
+ public function getDomains();
+
+ /**
+ * Gets the messages within a given domain.
+ *
+ * If $domain is null, it returns all messages.
+ *
+ * @param string $domain The domain name
+ *
+ * @return array An array of messages
+ */
+ public function all(string $domain = null);
+
+ /**
+ * Sets a message translation.
+ *
+ * @param string $id The message id
+ * @param string $translation The messages translation
+ * @param string $domain The domain name
+ */
+ public function set(string $id, string $translation, string $domain = 'messages');
+
+ /**
+ * Checks if a message has a translation.
+ *
+ * @param string $id The message id
+ * @param string $domain The domain name
+ *
+ * @return bool true if the message has a translation, false otherwise
+ */
+ public function has(string $id, string $domain = 'messages');
+
+ /**
+ * Checks if a message has a translation (it does not take into account the fallback mechanism).
+ *
+ * @param string $id The message id
+ * @param string $domain The domain name
+ *
+ * @return bool true if the message has a translation, false otherwise
+ */
+ public function defines(string $id, string $domain = 'messages');
+
+ /**
+ * Gets a message translation.
+ *
+ * @param string $id The message id
+ * @param string $domain The domain name
+ *
+ * @return string The message translation
+ */
+ public function get(string $id, string $domain = 'messages');
+
+ /**
+ * Sets translations for a given domain.
+ *
+ * @param array $messages An array of translations
+ * @param string $domain The domain name
+ */
+ public function replace(array $messages, string $domain = 'messages');
+
+ /**
+ * Adds translations for a given domain.
+ *
+ * @param array $messages An array of translations
+ * @param string $domain The domain name
+ */
+ public function add(array $messages, string $domain = 'messages');
+
+ /**
+ * Merges translations from the given Catalogue into the current one.
+ *
+ * The two catalogues must have the same locale.
+ */
+ public function addCatalogue(self $catalogue);
+
+ /**
+ * Merges translations from the given Catalogue into the current one
+ * only when the translation does not exist.
+ *
+ * This is used to provide default translations when they do not exist for the current locale.
+ */
+ public function addFallbackCatalogue(self $catalogue);
+
+ /**
+ * Gets the fallback catalogue.
+ *
+ * @return self|null A MessageCatalogueInterface instance or null when no fallback has been set
+ */
+ public function getFallbackCatalogue();
+
+ /**
+ * Returns an array of resources loaded to build this collection.
+ *
+ * @return ResourceInterface[] An array of resources
+ */
+ public function getResources();
+
+ /**
+ * Adds a resource for this collection.
+ */
+ public function addResource(ResourceInterface $resource);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MetadataAwareInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MetadataAwareInterface.php
new file mode 100644
index 0000000..2216eed
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MetadataAwareInterface.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+/**
+ * MetadataAwareInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface MetadataAwareInterface
+{
+ /**
+ * Gets metadata for the given domain and key.
+ *
+ * Passing an empty domain will return an array with all metadata indexed by
+ * domain and then by key. Passing an empty key will return an array with all
+ * metadata for the given domain.
+ *
+ * @return mixed The value that was set or an array with the domains/keys or null
+ */
+ public function getMetadata(string $key = '', string $domain = 'messages');
+
+ /**
+ * Adds metadata to a message domain.
+ *
+ * @param mixed $value
+ */
+ public function setMetadata(string $key, $value, string $domain = 'messages');
+
+ /**
+ * Deletes metadata for the given key and domain.
+ *
+ * Passing an empty domain will delete all metadata. Passing an empty key will
+ * delete all metadata for the given domain.
+ */
+ public function deleteMetadata(string $key = '', string $domain = 'messages');
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/AbstractProviderFactory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/AbstractProviderFactory.php
new file mode 100644
index 0000000..17442fd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/AbstractProviderFactory.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\IncompleteDsnException;
+
+abstract class AbstractProviderFactory implements ProviderFactoryInterface
+{
+ public function supports(Dsn $dsn): bool
+ {
+ return \in_array($dsn->getScheme(), $this->getSupportedSchemes(), true);
+ }
+
+ /**
+ * @return string[]
+ */
+ abstract protected function getSupportedSchemes(): array;
+
+ protected function getUser(Dsn $dsn): string
+ {
+ if (null === $user = $dsn->getUser()) {
+ throw new IncompleteDsnException('User is not set.', $dsn->getOriginalDsn());
+ }
+
+ return $user;
+ }
+
+ protected function getPassword(Dsn $dsn): string
+ {
+ if (null === $password = $dsn->getPassword()) {
+ throw new IncompleteDsnException('Password is not set.', $dsn->getOriginalDsn());
+ }
+
+ return $password;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/Dsn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/Dsn.php
new file mode 100644
index 0000000..820cabf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/Dsn.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\MissingRequiredOptionException;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Oskar Stark <oskarstark@googlemail.com>
+ */
+final class Dsn
+{
+ private $scheme;
+ private $host;
+ private $user;
+ private $password;
+ private $port;
+ private $path;
+ private $options;
+ private $originalDsn;
+
+ public function __construct(string $dsn)
+ {
+ $this->originalDsn = $dsn;
+
+ if (false === $parsedDsn = parse_url($dsn)) {
+ throw new InvalidArgumentException(sprintf('The "%s" translation provider DSN is invalid.', $dsn));
+ }
+
+ if (!isset($parsedDsn['scheme'])) {
+ throw new InvalidArgumentException(sprintf('The "%s" translation provider DSN must contain a scheme.', $dsn));
+ }
+ $this->scheme = $parsedDsn['scheme'];
+
+ if (!isset($parsedDsn['host'])) {
+ throw new InvalidArgumentException(sprintf('The "%s" translation provider DSN must contain a host (use "default" by default).', $dsn));
+ }
+ $this->host = $parsedDsn['host'];
+
+ $this->user = '' !== ($parsedDsn['user'] ?? '') ? urldecode($parsedDsn['user']) : null;
+ $this->password = '' !== ($parsedDsn['pass'] ?? '') ? urldecode($parsedDsn['pass']) : null;
+ $this->port = $parsedDsn['port'] ?? null;
+ $this->path = $parsedDsn['path'] ?? null;
+ parse_str($parsedDsn['query'] ?? '', $this->options);
+ }
+
+ public function getScheme(): string
+ {
+ return $this->scheme;
+ }
+
+ public function getHost(): string
+ {
+ return $this->host;
+ }
+
+ public function getUser(): ?string
+ {
+ return $this->user;
+ }
+
+ public function getPassword(): ?string
+ {
+ return $this->password;
+ }
+
+ public function getPort(int $default = null): ?int
+ {
+ return $this->port ?? $default;
+ }
+
+ public function getOption(string $key, $default = null)
+ {
+ return $this->options[$key] ?? $default;
+ }
+
+ public function getRequiredOption(string $key)
+ {
+ if (!\array_key_exists($key, $this->options) || '' === trim($this->options[$key])) {
+ throw new MissingRequiredOptionException($key);
+ }
+
+ return $this->options[$key];
+ }
+
+ public function getOptions(): array
+ {
+ return $this->options;
+ }
+
+ public function getPath(): ?string
+ {
+ return $this->path;
+ }
+
+ public function getOriginalDsn(): string
+ {
+ return $this->originalDsn;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/FilteringProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/FilteringProvider.php
new file mode 100644
index 0000000..0307cda
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/FilteringProvider.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\TranslatorBag;
+use Symfony\Component\Translation\TranslatorBagInterface;
+
+/**
+ * Filters domains and locales between the Translator config values and those specific to each provider.
+ *
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+class FilteringProvider implements ProviderInterface
+{
+ private $provider;
+ private $locales;
+ private $domains;
+
+ public function __construct(ProviderInterface $provider, array $locales, array $domains = [])
+ {
+ $this->provider = $provider;
+ $this->locales = $locales;
+ $this->domains = $domains;
+ }
+
+ public function __toString(): string
+ {
+ return (string) $this->provider;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write(TranslatorBagInterface $translatorBag): void
+ {
+ $this->provider->write($translatorBag);
+ }
+
+ public function read(array $domains, array $locales): TranslatorBag
+ {
+ $domains = !$this->domains ? $domains : array_intersect($this->domains, $domains);
+ $locales = array_intersect($this->locales, $locales);
+
+ return $this->provider->read($domains, $locales);
+ }
+
+ public function delete(TranslatorBagInterface $translatorBag): void
+ {
+ $this->provider->delete($translatorBag);
+ }
+
+ public function getDomains(): array
+ {
+ return $this->domains;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProvider.php
new file mode 100644
index 0000000..785fcaa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProvider.php
@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\TranslatorBag;
+use Symfony\Component\Translation\TranslatorBagInterface;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+class NullProvider implements ProviderInterface
+{
+ public function __toString(): string
+ {
+ return 'null';
+ }
+
+ public function write(TranslatorBagInterface $translatorBag, bool $override = false): void
+ {
+ }
+
+ public function read(array $domains, array $locales): TranslatorBag
+ {
+ return new TranslatorBag();
+ }
+
+ public function delete(TranslatorBagInterface $translatorBag): void
+ {
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProviderFactory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProviderFactory.php
new file mode 100644
index 0000000..6ddbd85
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProviderFactory.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\UnsupportedSchemeException;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+final class NullProviderFactory extends AbstractProviderFactory
+{
+ public function create(Dsn $dsn): ProviderInterface
+ {
+ if ('null' === $dsn->getScheme()) {
+ return new NullProvider();
+ }
+
+ throw new UnsupportedSchemeException($dsn, 'null', $this->getSupportedSchemes());
+ }
+
+ protected function getSupportedSchemes(): array
+ {
+ return ['null'];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderFactoryInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderFactoryInterface.php
new file mode 100644
index 0000000..3fd4494
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderFactoryInterface.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\IncompleteDsnException;
+use Symfony\Component\Translation\Exception\UnsupportedSchemeException;
+
+interface ProviderFactoryInterface
+{
+ /**
+ * @throws UnsupportedSchemeException
+ * @throws IncompleteDsnException
+ */
+ public function create(Dsn $dsn): ProviderInterface;
+
+ public function supports(Dsn $dsn): bool;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderInterface.php
new file mode 100644
index 0000000..a32193f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderInterface.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\TranslatorBag;
+use Symfony\Component\Translation\TranslatorBagInterface;
+
+interface ProviderInterface
+{
+ public function __toString(): string;
+
+ /**
+ * Translations available in the TranslatorBag only must be created.
+ * Translations available in both the TranslatorBag and on the provider
+ * must be overwritten.
+ * Translations available on the provider only must be kept.
+ */
+ public function write(TranslatorBagInterface $translatorBag): void;
+
+ public function read(array $domains, array $locales): TranslatorBag;
+
+ public function delete(TranslatorBagInterface $translatorBag): void;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollection.php
new file mode 100644
index 0000000..9963cb9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollection.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+final class TranslationProviderCollection
+{
+ private $providers;
+
+ /**
+ * @param array<string, ProviderInterface> $providers
+ */
+ public function __construct(iterable $providers)
+ {
+ $this->providers = [];
+ foreach ($providers as $name => $provider) {
+ $this->providers[$name] = $provider;
+ }
+ }
+
+ public function __toString(): string
+ {
+ return '['.implode(',', array_keys($this->providers)).']';
+ }
+
+ public function has(string $name): bool
+ {
+ return isset($this->providers[$name]);
+ }
+
+ public function get(string $name): ProviderInterface
+ {
+ if (!$this->has($name)) {
+ throw new InvalidArgumentException(sprintf('Provider "%s" not found. Available: "%s".', $name, (string) $this));
+ }
+
+ return $this->providers[$name];
+ }
+
+ public function keys(): array
+ {
+ return array_keys($this->providers);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php
new file mode 100644
index 0000000..43f4a34
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\UnsupportedSchemeException;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+class TranslationProviderCollectionFactory
+{
+ private $factories;
+ private $enabledLocales;
+
+ /**
+ * @param ProviderFactoryInterface[] $factories
+ */
+ public function __construct(iterable $factories, array $enabledLocales)
+ {
+ $this->factories = $factories;
+ $this->enabledLocales = $enabledLocales;
+ }
+
+ public function fromConfig(array $config): TranslationProviderCollection
+ {
+ $providers = [];
+ foreach ($config as $name => $currentConfig) {
+ $providers[$name] = $this->fromDsnObject(
+ new Dsn($currentConfig['dsn']),
+ !$currentConfig['locales'] ? $this->enabledLocales : $currentConfig['locales'],
+ !$currentConfig['domains'] ? [] : $currentConfig['domains']
+ );
+ }
+
+ return new TranslationProviderCollection($providers);
+ }
+
+ public function fromDsnObject(Dsn $dsn, array $locales, array $domains = []): ProviderInterface
+ {
+ foreach ($this->factories as $factory) {
+ if ($factory->supports($dsn)) {
+ return new FilteringProvider($factory->create($dsn), $locales, $domains);
+ }
+ }
+
+ throw new UnsupportedSchemeException($dsn);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/PseudoLocalizationTranslator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/PseudoLocalizationTranslator.php
new file mode 100644
index 0000000..49f122e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/PseudoLocalizationTranslator.php
@@ -0,0 +1,364 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+/**
+ * This translator should only be used in a development environment.
+ */
+final class PseudoLocalizationTranslator implements TranslatorInterface
+{
+ private const EXPANSION_CHARACTER = '~';
+
+ private $translator;
+ private $accents;
+ private $expansionFactor;
+ private $brackets;
+ private $parseHTML;
+ private $localizableHTMLAttributes;
+
+ /**
+ * Available options:
+ * * accents:
+ * type: boolean
+ * default: true
+ * description: replace ASCII characters of the translated string with accented versions or similar characters
+ * example: if true, "foo" => "ƒöö".
+ *
+ * * expansion_factor:
+ * type: float
+ * default: 1
+ * validation: it must be greater than or equal to 1
+ * description: expand the translated string by the given factor with spaces and tildes
+ * example: if 2, "foo" => "~foo ~"
+ *
+ * * brackets:
+ * type: boolean
+ * default: true
+ * description: wrap the translated string with brackets
+ * example: if true, "foo" => "[foo]"
+ *
+ * * parse_html:
+ * type: boolean
+ * default: false
+ * description: parse the translated string as HTML - looking for HTML tags has a performance impact but allows to preserve them from alterations - it also allows to compute the visible translated string length which is useful to correctly expand ot when it contains HTML
+ * warning: unclosed tags are unsupported, they will be fixed (closed) by the parser - eg, "foo <div>bar" => "foo <div>bar</div>"
+ *
+ * * localizable_html_attributes:
+ * type: string[]
+ * default: []
+ * description: the list of HTML attributes whose values can be altered - it is only useful when the "parse_html" option is set to true
+ * example: if ["title"], and with the "accents" option set to true, "<a href="#" title="Go to your profile">Profile</a>" => "<a href="#" title="Ĝö ţö ýöûŕ þŕöƒîļé">Þŕöƒîļé</a>" - if "title" was not in the "localizable_html_attributes" list, the title attribute data would be left unchanged.
+ */
+ public function __construct(TranslatorInterface $translator, array $options = [])
+ {
+ $this->translator = $translator;
+ $this->accents = $options['accents'] ?? true;
+
+ if (1.0 > ($this->expansionFactor = $options['expansion_factor'] ?? 1.0)) {
+ throw new \InvalidArgumentException('The expansion factor must be greater than or equal to 1.');
+ }
+
+ $this->brackets = $options['brackets'] ?? true;
+
+ $this->parseHTML = $options['parse_html'] ?? false;
+ if ($this->parseHTML && !$this->accents && 1.0 === $this->expansionFactor) {
+ $this->parseHTML = false;
+ }
+
+ $this->localizableHTMLAttributes = $options['localizable_html_attributes'] ?? [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null)
+ {
+ $trans = '';
+ $visibleText = '';
+
+ foreach ($this->getParts($this->translator->trans($id, $parameters, $domain, $locale)) as [$visible, $localizable, $text]) {
+ if ($visible) {
+ $visibleText .= $text;
+ }
+
+ if (!$localizable) {
+ $trans .= $text;
+
+ continue;
+ }
+
+ $this->addAccents($trans, $text);
+ }
+
+ $this->expand($trans, $visibleText);
+
+ $this->addBrackets($trans);
+
+ return $trans;
+ }
+
+ public function getLocale(): string
+ {
+ return $this->translator->getLocale();
+ }
+
+ private function getParts(string $originalTrans): array
+ {
+ if (!$this->parseHTML) {
+ return [[true, true, $originalTrans]];
+ }
+
+ $html = mb_convert_encoding($originalTrans, 'HTML-ENTITIES', mb_detect_encoding($originalTrans, null, true) ?: 'UTF-8');
+
+ $useInternalErrors = libxml_use_internal_errors(true);
+
+ $dom = new \DOMDocument();
+ $dom->loadHTML('<trans>'.$html.'</trans>');
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($useInternalErrors);
+
+ return $this->parseNode($dom->childNodes->item(1)->childNodes->item(0)->childNodes->item(0));
+ }
+
+ private function parseNode(\DOMNode $node): array
+ {
+ $parts = [];
+
+ foreach ($node->childNodes as $childNode) {
+ if (!$childNode instanceof \DOMElement) {
+ $parts[] = [true, true, $childNode->nodeValue];
+
+ continue;
+ }
+
+ $parts[] = [false, false, '<'.$childNode->tagName];
+
+ /** @var \DOMAttr $attribute */
+ foreach ($childNode->attributes as $attribute) {
+ $parts[] = [false, false, ' '.$attribute->nodeName.'="'];
+
+ $localizableAttribute = \in_array($attribute->nodeName, $this->localizableHTMLAttributes, true);
+ foreach (preg_split('/(&(?:amp|quot|#039|lt|gt);+)/', htmlspecialchars($attribute->nodeValue, \ENT_QUOTES, 'UTF-8'), -1, \PREG_SPLIT_DELIM_CAPTURE) as $i => $match) {
+ if ('' === $match) {
+ continue;
+ }
+
+ $parts[] = [false, $localizableAttribute && 0 === $i % 2, $match];
+ }
+
+ $parts[] = [false, false, '"'];
+ }
+
+ $parts[] = [false, false, '>'];
+
+ $parts = array_merge($parts, $this->parseNode($childNode, $parts));
+
+ $parts[] = [false, false, '</'.$childNode->tagName.'>'];
+ }
+
+ return $parts;
+ }
+
+ private function addAccents(string &$trans, string $text): void
+ {
+ $trans .= $this->accents ? strtr($text, [
+ ' ' => ' ',
+ '!' => '¡',
+ '"' => '″',
+ '#' => '♯',
+ '$' => '€',
+ '%' => '‰',
+ '&' => '⅋',
+ '\'' => '´',
+ '(' => '{',
+ ')' => '}',
+ '*' => '⁎',
+ '+' => '⁺',
+ ',' => '،',
+ '-' => '‐',
+ '.' => '·',
+ '/' => '⁄',
+ '0' => '⓪',
+ '1' => '①',
+ '2' => '②',
+ '3' => '③',
+ '4' => '④',
+ '5' => '⑤',
+ '6' => '⑥',
+ '7' => '⑦',
+ '8' => '⑧',
+ '9' => '⑨',
+ ':' => '∶',
+ ';' => '⁏',
+ '<' => '≤',
+ '=' => '≂',
+ '>' => '≥',
+ '?' => '¿',
+ '@' => '՞',
+ 'A' => 'Å',
+ 'B' => 'Ɓ',
+ 'C' => 'Ç',
+ 'D' => 'Ð',
+ 'E' => 'É',
+ 'F' => 'Ƒ',
+ 'G' => 'Ĝ',
+ 'H' => 'Ĥ',
+ 'I' => 'Î',
+ 'J' => 'Ĵ',
+ 'K' => 'Ķ',
+ 'L' => 'Ļ',
+ 'M' => 'Ṁ',
+ 'N' => 'Ñ',
+ 'O' => 'Ö',
+ 'P' => 'Þ',
+ 'Q' => 'Ǫ',
+ 'R' => 'Ŕ',
+ 'S' => 'Š',
+ 'T' => 'Ţ',
+ 'U' => 'Û',
+ 'V' => 'Ṽ',
+ 'W' => 'Ŵ',
+ 'X' => 'Ẋ',
+ 'Y' => 'Ý',
+ 'Z' => 'Ž',
+ '[' => '⁅',
+ '\\' => '∖',
+ ']' => '⁆',
+ '^' => '˄',
+ '_' => '‿',
+ '`' => '‵',
+ 'a' => 'å',
+ 'b' => 'ƀ',
+ 'c' => 'ç',
+ 'd' => 'ð',
+ 'e' => 'é',
+ 'f' => 'ƒ',
+ 'g' => 'ĝ',
+ 'h' => 'ĥ',
+ 'i' => 'î',
+ 'j' => 'ĵ',
+ 'k' => 'ķ',
+ 'l' => 'ļ',
+ 'm' => 'ɱ',
+ 'n' => 'ñ',
+ 'o' => 'ö',
+ 'p' => 'þ',
+ 'q' => 'ǫ',
+ 'r' => 'ŕ',
+ 's' => 'š',
+ 't' => 'ţ',
+ 'u' => 'û',
+ 'v' => 'ṽ',
+ 'w' => 'ŵ',
+ 'x' => 'ẋ',
+ 'y' => 'ý',
+ 'z' => 'ž',
+ '{' => '(',
+ '|' => '¦',
+ '}' => ')',
+ '~' => '˞',
+ ]) : $text;
+ }
+
+ private function expand(string &$trans, string $visibleText): void
+ {
+ if (1.0 >= $this->expansionFactor) {
+ return;
+ }
+
+ $visibleLength = $this->strlen($visibleText);
+ $missingLength = (int) (ceil($visibleLength * $this->expansionFactor)) - $visibleLength;
+ if ($this->brackets) {
+ $missingLength -= 2;
+ }
+
+ if (0 >= $missingLength) {
+ return;
+ }
+
+ $words = [];
+ $wordsCount = 0;
+ foreach (preg_split('/ +/', $visibleText, -1, \PREG_SPLIT_NO_EMPTY) as $word) {
+ $wordLength = $this->strlen($word);
+
+ if ($wordLength >= $missingLength) {
+ continue;
+ }
+
+ if (!isset($words[$wordLength])) {
+ $words[$wordLength] = 0;
+ }
+
+ ++$words[$wordLength];
+ ++$wordsCount;
+ }
+
+ if (!$words) {
+ $trans .= 1 === $missingLength ? self::EXPANSION_CHARACTER : ' '.str_repeat(self::EXPANSION_CHARACTER, $missingLength - 1);
+
+ return;
+ }
+
+ arsort($words, \SORT_NUMERIC);
+
+ $longestWordLength = max(array_keys($words));
+
+ while (true) {
+ $r = mt_rand(1, $wordsCount);
+
+ foreach ($words as $length => $count) {
+ $r -= $count;
+ if ($r <= 0) {
+ break;
+ }
+ }
+
+ $trans .= ' '.str_repeat(self::EXPANSION_CHARACTER, $length);
+
+ $missingLength -= $length + 1;
+
+ if (0 === $missingLength) {
+ return;
+ }
+
+ while ($longestWordLength >= $missingLength) {
+ $wordsCount -= $words[$longestWordLength];
+ unset($words[$longestWordLength]);
+
+ if (!$words) {
+ $trans .= 1 === $missingLength ? self::EXPANSION_CHARACTER : ' '.str_repeat(self::EXPANSION_CHARACTER, $missingLength - 1);
+
+ return;
+ }
+
+ $longestWordLength = max(array_keys($words));
+ }
+ }
+ }
+
+ private function addBrackets(string &$trans): void
+ {
+ if (!$this->brackets) {
+ return;
+ }
+
+ $trans = '['.$trans.']';
+ }
+
+ private function strlen(string $s): int
+ {
+ return false === ($encoding = mb_detect_encoding($s, null, true)) ? \strlen($s) : mb_strlen($s, $encoding);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/README.md
new file mode 100644
index 0000000..720bee3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/README.md
@@ -0,0 +1,33 @@
+Translation Component
+=====================
+
+The Translation component provides tools to internationalize your application.
+
+Getting Started
+---------------
+
+```
+$ composer require symfony/translation
+```
+
+```php
+use Symfony\Component\Translation\Translator;
+use Symfony\Component\Translation\Loader\ArrayLoader;
+
+$translator = new Translator('fr_FR');
+$translator->addLoader('array', new ArrayLoader());
+$translator->addResource('array', [
+ 'Hello World!' => 'Bonjour !',
+], 'fr_FR');
+
+echo $translator->trans('Hello World!'); // outputs « Bonjour ! »
+```
+
+Resources
+---------
+
+ * [Documentation](https://symfony.com/doc/current/translation.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReader.php
new file mode 100644
index 0000000..9e51b15
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReader.php
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Reader;
+
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationReader reads translation messages from translation files.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class TranslationReader implements TranslationReaderInterface
+{
+ /**
+ * Loaders used for import.
+ *
+ * @var array
+ */
+ private $loaders = [];
+
+ /**
+ * Adds a loader to the translation extractor.
+ *
+ * @param string $format The format of the loader
+ */
+ public function addLoader(string $format, LoaderInterface $loader)
+ {
+ $this->loaders[$format] = $loader;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function read(string $directory, MessageCatalogue $catalogue)
+ {
+ if (!is_dir($directory)) {
+ return;
+ }
+
+ foreach ($this->loaders as $format => $loader) {
+ // load any existing translation files
+ $finder = new Finder();
+ $extension = $catalogue->getLocale().'.'.$format;
+ $files = $finder->files()->name('*.'.$extension)->in($directory);
+ foreach ($files as $file) {
+ $domain = substr($file->getFilename(), 0, -1 * \strlen($extension) - 1);
+ $catalogue->addCatalogue($loader->load($file->getPathname(), $catalogue->getLocale(), $domain));
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReaderInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReaderInterface.php
new file mode 100644
index 0000000..bc37204
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReaderInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Reader;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationReader reads translation messages from translation files.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+interface TranslationReaderInterface
+{
+ /**
+ * Reads translation messages from a directory to the catalogue.
+ */
+ public function read(string $directory, MessageCatalogue $catalogue);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/bin/translation-status.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/bin/translation-status.php
new file mode 100644
index 0000000..4e0723b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/bin/translation-status.php
@@ -0,0 +1,207 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$usageInstructions = <<<END
+
+ Usage instructions
+ -------------------------------------------------------------------------------
+
+ $ cd symfony-code-root-directory/
+
+ # show the translation status of all locales
+ $ php translation-status.php
+
+ # show the translation status of all locales and all their missing translations
+ $ php translation-status.php -v
+
+ # show the status of a single locale
+ $ php translation-status.php fr
+
+ # show the status of a single locale and all its missing translations
+ $ php translation-status.php fr -v
+
+END;
+
+$config = [
+ // if TRUE, the full list of missing translations is displayed
+ 'verbose_output' => false,
+ // NULL = analyze all locales
+ 'locale_to_analyze' => null,
+ // the reference files all the other translations are compared to
+ 'original_files' => [
+ 'src/Symfony/Component/Form/Resources/translations/validators.en.xlf',
+ 'src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf',
+ 'src/Symfony/Component/Validator/Resources/translations/validators.en.xlf',
+ ],
+];
+
+$argc = $_SERVER['argc'];
+$argv = $_SERVER['argv'];
+
+if ($argc > 3) {
+ echo str_replace('translation-status.php', $argv[0], $usageInstructions);
+ exit(1);
+}
+
+foreach (array_slice($argv, 1) as $argumentOrOption) {
+ if (str_starts_with($argumentOrOption, '-')) {
+ $config['verbose_output'] = true;
+ } else {
+ $config['locale_to_analyze'] = $argumentOrOption;
+ }
+}
+
+foreach ($config['original_files'] as $originalFilePath) {
+ if (!file_exists($originalFilePath)) {
+ echo sprintf('The following file does not exist. Make sure that you execute this command at the root dir of the Symfony code repository.%s %s', \PHP_EOL, $originalFilePath);
+ exit(1);
+ }
+}
+
+$totalMissingTranslations = 0;
+
+foreach ($config['original_files'] as $originalFilePath) {
+ $translationFilePaths = findTranslationFiles($originalFilePath, $config['locale_to_analyze']);
+ $translationStatus = calculateTranslationStatus($originalFilePath, $translationFilePaths);
+
+ $totalMissingTranslations += array_sum(array_map(function ($translation) {
+ return count($translation['missingKeys']);
+ }, array_values($translationStatus)));
+
+ printTranslationStatus($originalFilePath, $translationStatus, $config['verbose_output']);
+}
+
+exit($totalMissingTranslations > 0 ? 1 : 0);
+
+function findTranslationFiles($originalFilePath, $localeToAnalyze)
+{
+ $translations = [];
+
+ $translationsDir = dirname($originalFilePath);
+ $originalFileName = basename($originalFilePath);
+ $translationFileNamePattern = str_replace('.en.', '.*.', $originalFileName);
+
+ $translationFiles = glob($translationsDir.'/'.$translationFileNamePattern, \GLOB_NOSORT);
+ sort($translationFiles);
+ foreach ($translationFiles as $filePath) {
+ $locale = extractLocaleFromFilePath($filePath);
+
+ if (null !== $localeToAnalyze && $locale !== $localeToAnalyze) {
+ continue;
+ }
+
+ $translations[$locale] = $filePath;
+ }
+
+ return $translations;
+}
+
+function calculateTranslationStatus($originalFilePath, $translationFilePaths)
+{
+ $translationStatus = [];
+ $allTranslationKeys = extractTranslationKeys($originalFilePath);
+
+ foreach ($translationFilePaths as $locale => $translationPath) {
+ $translatedKeys = extractTranslationKeys($translationPath);
+ $missingKeys = array_diff_key($allTranslationKeys, $translatedKeys);
+
+ $translationStatus[$locale] = [
+ 'total' => count($allTranslationKeys),
+ 'translated' => count($translatedKeys),
+ 'missingKeys' => $missingKeys,
+ ];
+ }
+
+ return $translationStatus;
+}
+
+function printTranslationStatus($originalFilePath, $translationStatus, $verboseOutput)
+{
+ printTitle($originalFilePath);
+ printTable($translationStatus, $verboseOutput);
+ echo \PHP_EOL.\PHP_EOL;
+}
+
+function extractLocaleFromFilePath($filePath)
+{
+ $parts = explode('.', $filePath);
+
+ return $parts[count($parts) - 2];
+}
+
+function extractTranslationKeys($filePath)
+{
+ $translationKeys = [];
+ $contents = new \SimpleXMLElement(file_get_contents($filePath));
+
+ foreach ($contents->file->body->{'trans-unit'} as $translationKey) {
+ $translationId = (string) $translationKey['id'];
+ $translationKey = (string) $translationKey->source;
+
+ $translationKeys[$translationId] = $translationKey;
+ }
+
+ return $translationKeys;
+}
+
+function printTitle($title)
+{
+ echo $title.\PHP_EOL;
+ echo str_repeat('=', strlen($title)).\PHP_EOL.\PHP_EOL;
+}
+
+function printTable($translations, $verboseOutput)
+{
+ if (0 === count($translations)) {
+ echo 'No translations found';
+
+ return;
+ }
+ $longestLocaleNameLength = max(array_map('strlen', array_keys($translations)));
+
+ foreach ($translations as $locale => $translation) {
+ if ($translation['translated'] > $translation['total']) {
+ textColorRed();
+ } elseif ($translation['translated'] === $translation['total']) {
+ textColorGreen();
+ }
+
+ echo sprintf('| Locale: %-'.$longestLocaleNameLength.'s | Translated: %d/%d', $locale, $translation['translated'], $translation['total']).\PHP_EOL;
+
+ textColorNormal();
+
+ if (true === $verboseOutput && count($translation['missingKeys']) > 0) {
+ echo str_repeat('-', 80).\PHP_EOL;
+ echo '| Missing Translations:'.\PHP_EOL;
+
+ foreach ($translation['missingKeys'] as $id => $content) {
+ echo sprintf('| (id=%s) %s', $id, $content).\PHP_EOL;
+ }
+
+ echo str_repeat('-', 80).\PHP_EOL;
+ }
+ }
+}
+
+function textColorGreen()
+{
+ echo "\033[32m";
+}
+
+function textColorRed()
+{
+ echo "\033[31m";
+}
+
+function textColorNormal()
+{
+ echo "\033[0m";
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/data/parents.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/data/parents.json
new file mode 100644
index 0000000..a67458a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/data/parents.json
@@ -0,0 +1,140 @@
+{
+ "az_Cyrl": "root",
+ "bs_Cyrl": "root",
+ "en_150": "en_001",
+ "en_AG": "en_001",
+ "en_AI": "en_001",
+ "en_AT": "en_150",
+ "en_AU": "en_001",
+ "en_BB": "en_001",
+ "en_BE": "en_150",
+ "en_BM": "en_001",
+ "en_BS": "en_001",
+ "en_BW": "en_001",
+ "en_BZ": "en_001",
+ "en_CA": "en_001",
+ "en_CC": "en_001",
+ "en_CH": "en_150",
+ "en_CK": "en_001",
+ "en_CM": "en_001",
+ "en_CX": "en_001",
+ "en_CY": "en_001",
+ "en_DE": "en_150",
+ "en_DG": "en_001",
+ "en_DK": "en_150",
+ "en_DM": "en_001",
+ "en_ER": "en_001",
+ "en_FI": "en_150",
+ "en_FJ": "en_001",
+ "en_FK": "en_001",
+ "en_FM": "en_001",
+ "en_GB": "en_001",
+ "en_GD": "en_001",
+ "en_GG": "en_001",
+ "en_GH": "en_001",
+ "en_GI": "en_001",
+ "en_GM": "en_001",
+ "en_GY": "en_001",
+ "en_HK": "en_001",
+ "en_IE": "en_001",
+ "en_IL": "en_001",
+ "en_IM": "en_001",
+ "en_IN": "en_001",
+ "en_IO": "en_001",
+ "en_JE": "en_001",
+ "en_JM": "en_001",
+ "en_KE": "en_001",
+ "en_KI": "en_001",
+ "en_KN": "en_001",
+ "en_KY": "en_001",
+ "en_LC": "en_001",
+ "en_LR": "en_001",
+ "en_LS": "en_001",
+ "en_MG": "en_001",
+ "en_MO": "en_001",
+ "en_MS": "en_001",
+ "en_MT": "en_001",
+ "en_MU": "en_001",
+ "en_MW": "en_001",
+ "en_MY": "en_001",
+ "en_NA": "en_001",
+ "en_NF": "en_001",
+ "en_NG": "en_001",
+ "en_NL": "en_150",
+ "en_NR": "en_001",
+ "en_NU": "en_001",
+ "en_NZ": "en_001",
+ "en_PG": "en_001",
+ "en_PH": "en_001",
+ "en_PK": "en_001",
+ "en_PN": "en_001",
+ "en_PW": "en_001",
+ "en_RW": "en_001",
+ "en_SB": "en_001",
+ "en_SC": "en_001",
+ "en_SD": "en_001",
+ "en_SE": "en_150",
+ "en_SG": "en_001",
+ "en_SH": "en_001",
+ "en_SI": "en_150",
+ "en_SL": "en_001",
+ "en_SS": "en_001",
+ "en_SX": "en_001",
+ "en_SZ": "en_001",
+ "en_TC": "en_001",
+ "en_TK": "en_001",
+ "en_TO": "en_001",
+ "en_TT": "en_001",
+ "en_TV": "en_001",
+ "en_TZ": "en_001",
+ "en_UG": "en_001",
+ "en_VC": "en_001",
+ "en_VG": "en_001",
+ "en_VU": "en_001",
+ "en_WS": "en_001",
+ "en_ZA": "en_001",
+ "en_ZM": "en_001",
+ "en_ZW": "en_001",
+ "es_AR": "es_419",
+ "es_BO": "es_419",
+ "es_BR": "es_419",
+ "es_BZ": "es_419",
+ "es_CL": "es_419",
+ "es_CO": "es_419",
+ "es_CR": "es_419",
+ "es_CU": "es_419",
+ "es_DO": "es_419",
+ "es_EC": "es_419",
+ "es_GT": "es_419",
+ "es_HN": "es_419",
+ "es_MX": "es_419",
+ "es_NI": "es_419",
+ "es_PA": "es_419",
+ "es_PE": "es_419",
+ "es_PR": "es_419",
+ "es_PY": "es_419",
+ "es_SV": "es_419",
+ "es_US": "es_419",
+ "es_UY": "es_419",
+ "es_VE": "es_419",
+ "ff_Adlm": "root",
+ "nb": "no",
+ "nn": "no",
+ "pa_Arab": "root",
+ "pt_AO": "pt_PT",
+ "pt_CH": "pt_PT",
+ "pt_CV": "pt_PT",
+ "pt_GQ": "pt_PT",
+ "pt_GW": "pt_PT",
+ "pt_LU": "pt_PT",
+ "pt_MO": "pt_PT",
+ "pt_MZ": "pt_PT",
+ "pt_ST": "pt_PT",
+ "pt_TL": "pt_PT",
+ "sd_Deva": "root",
+ "sr_Latn": "root",
+ "uz_Arab": "root",
+ "uz_Cyrl": "root",
+ "zh_Hant": "root",
+ "zh_Hant_MO": "zh_Hant_HK"
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/functions.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/functions.php
new file mode 100644
index 0000000..901d2f8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/functions.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+if (!\function_exists(t::class)) {
+ /**
+ * @author Nate Wiebe <nate@northern.co>
+ */
+ function t(string $message, array $parameters = [], string $domain = null): TranslatableMessage
+ {
+ return new TranslatableMessage($message, $parameters, $domain);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd
new file mode 100644
index 0000000..dface62
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd
@@ -0,0 +1,2223 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+
+May-19-2004:
+- Changed the <choice> for ElemType_header, moving minOccurs="0" maxOccurs="unbounded" from its elements
+to <choice> itself.
+- Added <choice> for ElemType_trans-unit to allow "any order" for <context-group>, <count-group>, <prop-group>, <note>, and
+<alt-trans>.
+
+Oct-2005
+- updated version info to 1.2
+- equiv-trans attribute to <trans-unit> element
+- merged-trans attribute for <group> element
+- Add the <seg-source> element as optional in the <trans-unit> and <alt-trans> content models, at the same level as <source>
+- Create a new value "seg" for the mtype attribute of the <mrk> element
+- Add mid as an optional attribute for the <alt-trans> element
+
+Nov-14-2005
+- Changed name attribute for <context-group> from required to optional
+- Added extension point at <xliff>
+
+Jan-9-2006
+- Added alttranstype type attribute to <alt-trans>, and values
+
+Jan-10-2006
+- Corrected error with overwritten purposeValueList
+- Corrected name="AttrType_Version", attribute should have been "name"
+
+-->
+<xsd:schema xmlns:xlf="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:xliff:document:1.2" xml:lang="en">
+ <!-- Import for xml:lang and xml:space -->
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ <!-- Attributes Lists -->
+ <xsd:simpleType name="XTend">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="x-[^\s]+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="context-typeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'context-type'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="database">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a database content.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="element">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the content of an element within an XML document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="elementtitle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the name of an element within an XML document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="linenumber">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="numparams">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a the number of parameters contained within the <source>.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="paramnotes">
+ <xsd:annotation>
+ <xsd:documentation>Indicates notes pertaining to the parameters in the <source>.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="record">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the content of a record within a database.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="recordtitle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the name of a record within a database.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sourcefile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="count-typeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'count-type'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="num-usages">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="repetition">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the count units are translation units existing already in the same document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="total">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a total count.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="InlineDelimitersValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'ctype' when used other elements than <ph> or <x>.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="bold">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of bolded text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="italic">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of text in italics.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="underlined">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of underlined text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="link">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of hyper-text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="InlinePlaceholdersValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'ctype' when used with <ph> or <x>.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="image">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a inline image.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pb">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a page break.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="lb">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a line break.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="mime-typeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="(text|multipart|message|application|image|audio|video|model)(/.+)*"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="datatypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'datatype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="asp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Active Server Page data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="c">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cdf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Channel Definition Format (CDF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cfm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates ColdFusion data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cpp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C++ source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="csharp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C-Sharp data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cstring">
+ <xsd:annotation>
+ <xsd:documentation>Indicates strings from C, ASM, and driver files data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="csv">
+ <xsd:annotation>
+ <xsd:documentation>Indicates comma-separated values data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="database">
+ <xsd:annotation>
+ <xsd:documentation>Indicates database data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="documentfooter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates portions of document that follows data and contains metadata.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="documentheader">
+ <xsd:annotation>
+ <xsd:documentation>Indicates portions of document that precedes data and contains metadata.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="filedialog">
+ <xsd:annotation>
+ <xsd:documentation>Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="form">
+ <xsd:annotation>
+ <xsd:documentation>Indicates standard user input screen data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="html">
+ <xsd:annotation>
+ <xsd:documentation>Indicates HyperText Markup Language (HTML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="htmlbody">
+ <xsd:annotation>
+ <xsd:documentation>Indicates content within an HTML document’s <body> element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ini">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows INI file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="interleaf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Interleaf data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javaclass">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java source file data (extension '.java').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javapropertyresourcebundle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java property resource bundle data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javalistresourcebundle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java list resource bundle data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javascript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates JavaScript source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="jscript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates JScript source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="layout">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information relating to formatting.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="lisp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates LISP source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="margin">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information relating to margin formats.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menufile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a file containing menu.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="messagefile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates numerically identified string table.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mif">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Maker Interchange Format (MIF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mimetype">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mo">
+ <xsd:annotation>
+ <xsd:documentation>Indicates GNU Machine Object data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="msglib">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Message Librarian strings created by Novell's Message Librarian Tool.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pagefooter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information to be displayed at the bottom of each page of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pageheader">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information to be displayed at the top of each page of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="parameters">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list of property values (e.g., settings within INI files or preferences dialog).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pascal">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Pascal source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="php">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Hypertext Preprocessor data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="plaintext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates plain text file (no formatting other than, possibly, wrapping).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="po">
+ <xsd:annotation>
+ <xsd:documentation>Indicates GNU Portable Object file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="report">
+ <xsd:annotation>
+ <xsd:documentation>Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="resources">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows .NET binary resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="resx">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows .NET Resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rtf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Rich Text Format (RTF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sgml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sgmldtd">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="svg">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Scalable Vector Graphic (SVG) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="vbscript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates VisualBasic Script source file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="warning">
+ <xsd:annotation>
+ <xsd:documentation>Indicates warning message.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="winres">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xhtml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible HyperText Markup Language (XHTML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Markup Language (XML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xmldtd">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xsl">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Stylesheet Language (XSL) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xul">
+ <xsd:annotation>
+ <xsd:documentation>Indicates XUL elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="mtypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'mtype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="abbrev">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is an abbreviation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="abbreviated-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="abbreviation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="acronym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="appellation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620: A proper-name term, such as the name of an agency or other proper entity.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="collocation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="common-name">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="datetime">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a date and/or time.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="equation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="expanded-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="formula">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="head-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="initialism">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="international-scientific-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="internationalism">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="logical-expression">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="materials-management-unit">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17: A unit to track object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="name">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a name.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="near-synonym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="part-number">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="phrase">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="phraseological-unit">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="protected">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text should not be translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="romanized-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="seg">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the marked text represents a segment.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="set-phrase">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.2: A fixed, lexicalized phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="short-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sku">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="standard-text">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.19: A fixed chunk of recurring text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="symbol">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="synonym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="synonymous-phrase">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="term">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a term.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="transcribed-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="transliterated-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="truncated-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="variant">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.9: One of the alternate forms of a term.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="restypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'restype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="auto3state">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTO3STATE control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="autocheckbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTOCHECKBOX control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="autoradiobutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTORADIOBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC BEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bitmap">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a bitmap, for example a BITMAP resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="button">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a button object, for example a BUTTON control Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="caption">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a caption, such as the caption of a dialog box.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cell">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the cell in a table, for example the content of the <td> element in HTML.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates check box object, for example a CHECKBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkboxmenuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu item with an associated checkbox.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkedlistbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list box, but with a check-box for each item.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="colorchooser">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a color selection dialog.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="combobox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="comboboxexitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="comboboxitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="component">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI base class element that cannot be represented by any other element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="contextmenu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a context menu.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ctext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC CTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cursor">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a cursor, for example a CURSOR resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="datetimepicker">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a date/time picker.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="defpushbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC DEFPUSHBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dialog">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a dialog box.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dlginit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC DLGINIT resource block.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="edit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an edit box object, for example an EDIT control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="file">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a filename.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="filechooser">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a file dialog.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="fn">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a footnote.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a font name.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="footer">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a footer.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="frame">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a frame object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="grid">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL grid element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="groupbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a groupbox object, for example a GROUPBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="header">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a header item.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="heading">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="hedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC HEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="hscrollbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a horizontal scrollbar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="icon">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an icon, for example an ICON resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="iedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC IEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="keywords">
+ <xsd:annotation>
+ <xsd:documentation>Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="label">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a label object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="linklabel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a label that is also a HTML link (not necessarily a URL).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="list">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="listbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a listbox object, for example an LISTBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="listitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an list item (an entry in a list).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ltext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC LTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu (a group of menu-items).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menubar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a toolbar containing one or more tope level menus.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu item (an entry in a menu).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menuseparator">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL menuseparator element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="message">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a message, for example an entry in a MESSAGETABLE resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="monthcalendar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a calendar control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="numericupdown">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an edit box beside a spin control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="panel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a catch all for rectangular areas.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="popupmenu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a standalone menu not necessarily associated with a menubar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pushbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a pushbox object, for example a PUSHBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pushbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC PUSHBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="radio">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a radio button object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="radiobuttonmenuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menuitem with associated radio button.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rcdata">
+ <xsd:annotation>
+ <xsd:documentation>Indicates raw data resources for an application.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="row">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a row in a table.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rtext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC RTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="scrollpane">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a user navigable container used to show a portion of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="separator">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a generic divider object (e.g. menu group separator).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="shortcut">
+ <xsd:annotation>
+ <xsd:documentation>Windows accelerators, shortcuts in resource or property files.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="spinner">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI control to indicate process activity but not progress.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="splitter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a splitter bar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="state3">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC STATE3 control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="statusbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a window for providing feedback to the users, like 'read-only', etc.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="string">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a string, for example an entry in a STRINGTABLE resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tabcontrol">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a layers of controls with a tab to select layers.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="table">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a display and edits regular two-dimensional tables of cells.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="textbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL textbox element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="togglebutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI button that can be toggled to on or off state.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="toolbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an array of controls, usually buttons.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tooltip">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a pop up tool tip text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="trackbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a bar with a pointer indicating a position within a certain range.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tree">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a control that displays a set of hierarchical data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="uri">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a URI (URN or URL).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="userbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC USERBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="usercontrol">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a user-defined control like CONTROL control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="var">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the text of a variable.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="versioninfo">
+ <xsd:annotation>
+ <xsd:documentation>Indicates version information about a resource like VERSIONINFO in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="vscrollbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a vertical scrollbar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="window">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a graphical window.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="size-unitValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'size-unit'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="byte">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 8-bit bytes.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="char">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in Unicode characters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="col">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in columns. Used for HTML text area.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in centimeters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dlgunit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in dialog units, as defined in Windows resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="em">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 'font-size' units (as defined in CSS).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ex">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 'x-height' units (as defined in CSS).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="glyph">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster'</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="in">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in inches.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in millimeters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="percent">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in percentage.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pixel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in pixels.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="point">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in point.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="row">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in rows. Used for HTML text area.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="stateValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'state'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="final">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the terminating state.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-adaptation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates only non-textual information needs adaptation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-l10n">
+ <xsd:annotation>
+ <xsd:documentation>Indicates both text and non-textual information needs adaptation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-adaptation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates only non-textual information needs review.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-l10n">
+ <xsd:annotation>
+ <xsd:documentation>Indicates both text and non-textual information needs review.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-translation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that only the text of the item needs to be reviewed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-translation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item needs to be translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="new">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item is new. For example, translation units that were not in a previous version of the document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="signed-off">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that changes are reviewed and approved.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="translated">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="state-qualifierValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'state-qualifier'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="exact-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="fuzzy-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="id-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a match based on matching IDs (in addition to matching text).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-glossary">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a glossary.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-inherited">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from existing translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-mt">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from machine translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-repository">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a translation repository.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-tm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a translation memory.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mt-suggestion">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the translation is suggested by machine translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-grammar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because of incorrect grammar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-inaccurate">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because it is incorrect.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-length">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because it is too long or too short.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-spelling">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because of incorrect spelling.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tm-suggestion">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the translation is suggested by translation memory.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="unitValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'unit'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="word">
+ <xsd:annotation>
+ <xsd:documentation>Refers to words.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="page">
+ <xsd:annotation>
+ <xsd:documentation>Refers to pages.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="trans-unit">
+ <xsd:annotation>
+ <xsd:documentation>Refers to <trans-unit> elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bin-unit">
+ <xsd:annotation>
+ <xsd:documentation>Refers to <bin-unit> elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="glyph">
+ <xsd:annotation>
+ <xsd:documentation>Refers to glyphs.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="item">
+ <xsd:annotation>
+ <xsd:documentation>Refers to <trans-unit> and/or <bin-unit> elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="instance">
+ <xsd:annotation>
+ <xsd:documentation>Refers to the occurrences of instances defined by the count-type value.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="character">
+ <xsd:annotation>
+ <xsd:documentation>Refers to characters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="line">
+ <xsd:annotation>
+ <xsd:documentation>Refers to lines.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sentence">
+ <xsd:annotation>
+ <xsd:documentation>Refers to sentences.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="paragraph">
+ <xsd:annotation>
+ <xsd:documentation>Refers to paragraphs.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="segment">
+ <xsd:annotation>
+ <xsd:documentation>Refers to segments.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="placeable">
+ <xsd:annotation>
+ <xsd:documentation>Refers to placeables (inline elements).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="priorityValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'priority'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:positiveInteger">
+ <xsd:enumeration value="1">
+ <xsd:annotation>
+ <xsd:documentation>Highest priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="2">
+ <xsd:annotation>
+ <xsd:documentation>High priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="3">
+ <xsd:annotation>
+ <xsd:documentation>High priority, but not as important as 2.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="4">
+ <xsd:annotation>
+ <xsd:documentation>High priority, but not as important as 3.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="5">
+ <xsd:annotation>
+ <xsd:documentation>Medium priority, but more important than 6.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="6">
+ <xsd:annotation>
+ <xsd:documentation>Medium priority, but less important than 5.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="7">
+ <xsd:annotation>
+ <xsd:documentation>Low priority, but more important than 8.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="8">
+ <xsd:annotation>
+ <xsd:documentation>Low priority, but more important than 9.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="9">
+ <xsd:annotation>
+ <xsd:documentation>Low priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="10">
+ <xsd:annotation>
+ <xsd:documentation>Lowest priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="reformatValueYesNo">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="yes">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all properties can be reformatted. This value must be used alone.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="no">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that no properties should be reformatted. This value must be used alone.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="reformatValueList">
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:union memberTypes="xlf:XTend">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="coord">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-x">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the x information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-y">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the y information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-cx">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the cx information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-cy">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the cy information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all the information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-name">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the name information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-size">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the size information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-weight">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the weight information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="css-style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the css-style attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the style attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ex-style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the exstyle attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ <xsd:simpleType name="purposeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="information">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="location">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="alttranstypeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="proposal">
+ <xsd:annotation>
+ <xsd:documentation>Represents a translation proposal from a translation memory or other resource.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="previous-version">
+ <xsd:annotation>
+ <xsd:documentation>Represents a previous version of the target element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected">
+ <xsd:annotation>
+ <xsd:documentation>Represents a rejected version of the target element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="reference">
+ <xsd:annotation>
+ <xsd:documentation>Represents a translation to be used for reference purposes only, for example from a related product or a different language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="accepted">
+ <xsd:annotation>
+ <xsd:documentation>Represents a proposed translation that was used for the translation of the trans-unit, possibly modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <!-- Other Types -->
+ <xsd:complexType name="ElemType_ExternalReference">
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ </xsd:complexType>
+ <xsd:simpleType name="AttrType_purpose">
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:union memberTypes="xlf:purposeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_datatype">
+ <xsd:union memberTypes="xlf:datatypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_restype">
+ <xsd:union memberTypes="xlf:restypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_alttranstype">
+ <xsd:union memberTypes="xlf:alttranstypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_context-type">
+ <xsd:union memberTypes="xlf:context-typeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_state">
+ <xsd:union memberTypes="xlf:stateValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_state-qualifier">
+ <xsd:union memberTypes="xlf:state-qualifierValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_count-type">
+ <xsd:union memberTypes="xlf:restypeValueList xlf:count-typeValueList xlf:datatypeValueList xlf:stateValueList xlf:state-qualifierValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_InlineDelimiters">
+ <xsd:union memberTypes="xlf:InlineDelimitersValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_InlinePlaceholders">
+ <xsd:union memberTypes="xlf:InlinePlaceholdersValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_size-unit">
+ <xsd:union memberTypes="xlf:size-unitValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_mtype">
+ <xsd:union memberTypes="xlf:mtypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_unit">
+ <xsd:union memberTypes="xlf:unitValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_priority">
+ <xsd:union memberTypes="xlf:priorityValueList"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_reformat">
+ <xsd:union memberTypes="xlf:reformatValueYesNo xlf:reformatValueList"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_YesNo">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="yes"/>
+ <xsd:enumeration value="no"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Position">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="open"/>
+ <xsd:enumeration value="close"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_assoc">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="preceding"/>
+ <xsd:enumeration value="following"/>
+ <xsd:enumeration value="both"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_annotates">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="source"/>
+ <xsd:enumeration value="target"/>
+ <xsd:enumeration value="general"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Coordinates">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'coord'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="(-?\d+|#);(-?\d+|#);(-?\d+|#);(-?\d+|#)"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Version">
+ <xsd:annotation>
+ <xsd:documentation>Version values: 1.0 and 1.1 are allowed for backward compatibility.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="1.2"/>
+ <xsd:enumeration value="1.1"/>
+ <xsd:enumeration value="1.0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <!-- Groups -->
+ <xsd:group name="ElemGroup_TextContent">
+ <xsd:choice>
+ <xsd:element ref="xlf:g"/>
+ <xsd:element ref="xlf:bpt"/>
+ <xsd:element ref="xlf:ept"/>
+ <xsd:element ref="xlf:ph"/>
+ <xsd:element ref="xlf:it"/>
+ <xsd:element ref="xlf:mrk"/>
+ <xsd:element ref="xlf:x"/>
+ <xsd:element ref="xlf:bx"/>
+ <xsd:element ref="xlf:ex"/>
+ </xsd:choice>
+ </xsd:group>
+ <xsd:attributeGroup name="AttrGroup_TextContent">
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="xid" type="xsd:string" use="optional"/>
+ <xsd:attribute name="equiv-text" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:attributeGroup>
+ <!-- XLIFF Structure -->
+ <xsd:element name="xliff">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ <xsd:element ref="xlf:file"/>
+ </xsd:sequence>
+ <xsd:attribute name="version" type="xlf:AttrType_Version" use="required"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="file">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" ref="xlf:header"/>
+ <xsd:element ref="xlf:body"/>
+ </xsd:sequence>
+ <xsd:attribute name="original" type="xsd:string" use="required"/>
+ <xsd:attribute name="source-language" type="xsd:language" use="required"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="required"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
+ <xsd:attribute ref="xml:space" use="optional"/>
+ <xsd:attribute name="category" type="xsd:string" use="optional"/>
+ <xsd:attribute name="target-language" type="xsd:language" use="optional"/>
+ <xsd:attribute name="product-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="product-version" type="xsd:string" use="optional"/>
+ <xsd:attribute name="build-num" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_group_id">
+ <xsd:selector xpath=".//xlf:group"/>
+ <xsd:field xpath="@id"/>
+ </xsd:unique>
+ <xsd:key name="K_unit_id">
+ <xsd:selector xpath=".//xlf:trans-unit|.//xlf:bin-unit"/>
+ <xsd:field xpath="@id"/>
+ </xsd:key>
+ <xsd:keyref name="KR_unit_id" refer="xlf:K_unit_id">
+ <xsd:selector xpath=".//bpt|.//ept|.//it|.//ph|.//g|.//x|.//bx|.//ex|.//sub"/>
+ <xsd:field xpath="@xid"/>
+ </xsd:keyref>
+ <xsd:key name="K_tool-id">
+ <xsd:selector xpath="xlf:header/xlf:tool"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:key>
+ <xsd:keyref name="KR_file_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath="."/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:keyref name="KR_phase_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:keyref name="KR_alt-trans_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath=".//xlf:trans-unit/xlf:alt-trans"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:key name="K_count-group_name">
+ <xsd:selector xpath=".//xlf:count-group"/>
+ <xsd:field xpath="@name"/>
+ </xsd:key>
+ <xsd:unique name="U_context-group_name">
+ <xsd:selector xpath=".//xlf:context-group"/>
+ <xsd:field xpath="@name"/>
+ </xsd:unique>
+ <xsd:key name="K_phase-name">
+ <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
+ <xsd:field xpath="@phase-name"/>
+ </xsd:key>
+ <xsd:keyref name="KR_phase-name" refer="xlf:K_phase-name">
+ <xsd:selector xpath=".//xlf:count|.//xlf:trans-unit|.//xlf:target|.//bin-unit|.//bin-target"/>
+ <xsd:field xpath="@phase-name"/>
+ </xsd:keyref>
+ <xsd:unique name="U_uid">
+ <xsd:selector xpath=".//xlf:external-file"/>
+ <xsd:field xpath="@uid"/>
+ </xsd:unique>
+ </xsd:element>
+ <xsd:element name="header">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="skl" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element minOccurs="0" ref="xlf:phase-group"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element name="glossary" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element name="reference" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:tool"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="internal-file">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="form" type="xsd:string"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="external-file">
+ <xsd:complexType>
+ <xsd:attribute name="href" type="xsd:string" use="required"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
+ <xsd:attribute name="uid" type="xsd:NMTOKEN"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="note">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute default="1" name="priority" type="xlf:AttrType_priority" use="optional"/>
+ <xsd:attribute name="from" type="xsd:string" use="optional"/>
+ <xsd:attribute default="general" name="annotates" type="xlf:AttrType_annotates" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="phase-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:element ref="xlf:phase"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="phase">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:note"/>
+ </xsd:sequence>
+ <xsd:attribute name="phase-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="process-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="company-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
+ <xsd:attribute name="job-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-email" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-phone" type="xsd:string" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="count-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:count"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="count">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="count-type" type="xlf:AttrType_count-type" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:attribute default="word" name="unit" type="xlf:AttrType_unit" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="context-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:element ref="xlf:context"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="purpose" type="xlf:AttrType_purpose" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="context">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="context-type" type="xlf:AttrType_context-type" use="required"/>
+ <xsd:attribute default="no" name="match-mandatory" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="tool">
+ <xsd:complexType mixed="true">
+ <xsd:sequence>
+ <xsd:any namespace="##any" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="tool-id" type="xsd:string" use="required"/>
+ <xsd:attribute name="tool-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="tool-version" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-company" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="body">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="group">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:count-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
+ </xsd:choice>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
+ <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
+ <xsd:attribute default="no" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="trans-unit">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xlf:source"/>
+ <xsd:element minOccurs="0" ref="xlf:seg-source"/>
+ <xsd:element minOccurs="0" ref="xlf:target"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:context-group"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:alt-trans"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
+ <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
+ <xsd:attribute default="yes" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_tu_segsrc_mid">
+ <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_tu_segsrc_mid" refer="xlf:U_tu_segsrc_mid">
+ <xsd:selector xpath="./xlf:target/xlf:mrk|./xlf:alt-trans"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="source">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_source_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_source_ept_rid" refer="xlf:U_source_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_source_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_source_ex_rid" refer="xlf:U_source_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="seg-source">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_segsrc_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_segsrc_ept_rid" refer="xlf:U_segsrc_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_segsrc_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_segsrc_ex_rid" refer="xlf:U_segsrc_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="target">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
+ <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="yes" name="equiv-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_target_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_target_ept_rid" refer="xlf:U_target_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_target_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_target_ex_rid" refer="xlf:U_target_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="alt-trans">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" ref="xlf:source"/>
+ <xsd:element minOccurs="0" ref="xlf:seg-source"/>
+ <xsd:element maxOccurs="1" ref="xlf:target"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="match-quality" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute name="origin" type="xsd:string" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="proposal" name="alttranstype" type="xlf:AttrType_alttranstype" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_at_segsrc_mid">
+ <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_at_segsrc_mid" refer="xlf:U_at_segsrc_mid">
+ <xsd:selector xpath="./xlf:target/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="bin-unit">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xlf:bin-source"/>
+ <xsd:element minOccurs="0" ref="xlf:bin-target"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:context-group"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:trans-unit"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="required"/>
+ <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bin-source">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bin-target">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="optional"/>
+ <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
+ <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <!-- Element for inline codes -->
+ <xsd:element name="g">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="x">
+ <xsd:complexType>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bx">
+ <xsd:complexType>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ex">
+ <xsd:complexType>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ph">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attribute name="assoc" type="xlf:AttrType_assoc" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bpt">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ept">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="it">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="pos" type="xlf:AttrType_Position" use="required"/>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="sub">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="xid" type="xsd:string" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="mrk">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="mtype" type="xlf:AttrType_mtype" use="required"/>
+ <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="comment" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+</xsd:schema>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd
new file mode 100644
index 0000000..963232f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd
@@ -0,0 +1,411 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ XLIFF Version 2.0
+ OASIS Standard
+ 05 August 2014
+ Copyright (c) OASIS Open 2014. All rights reserved.
+ Source: http://docs.oasis-open.org/xliff/xliff-core/v2.0/os/schemas/
+ -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified"
+ xmlns:xlf="urn:oasis:names:tc:xliff:document:2.0"
+ targetNamespace="urn:oasis:names:tc:xliff:document:2.0">
+
+ <!-- Import -->
+
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="informativeCopiesOf3rdPartySchemas/w3c/xml.xsd"/>
+
+ <!-- Element Group -->
+
+ <xs:group name="inline">
+ <xs:choice>
+ <xs:element ref="xlf:cp"/>
+ <xs:element ref="xlf:ph"/>
+ <xs:element ref="xlf:pc"/>
+ <xs:element ref="xlf:sc"/>
+ <xs:element ref="xlf:ec"/>
+ <xs:element ref="xlf:mrk"/>
+ <xs:element ref="xlf:sm"/>
+ <xs:element ref="xlf:em"/>
+ </xs:choice>
+ </xs:group>
+
+ <!-- Attribute Types -->
+
+ <xs:simpleType name="yesNo">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="yes"/>
+ <xs:enumeration value="no"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="yesNoFirstNo">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="yes"/>
+ <xs:enumeration value="firstNo"/>
+ <xs:enumeration value="no"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="dirValue">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="ltr"/>
+ <xs:enumeration value="rtl"/>
+ <xs:enumeration value="auto"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="appliesTo">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="source"/>
+ <xs:enumeration value="target"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="userDefinedValue">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[^\s:]+:[^\s:]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="attrType_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="fmt"/>
+ <xs:enumeration value="ui"/>
+ <xs:enumeration value="quote"/>
+ <xs:enumeration value="link"/>
+ <xs:enumeration value="image"/>
+ <xs:enumeration value="other"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="typeForMrkValues">
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="generic"/>
+ <xs:enumeration value="comment"/>
+ <xs:enumeration value="term"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="attrType_typeForMrk">
+ <xs:union memberTypes="xlf:typeForMrkValues xlf:userDefinedValue"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="priorityValue">
+ <xs:restriction base="xs:positiveInteger">
+ <xs:minInclusive value="1"/>
+ <xs:maxInclusive value="10"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="stateType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="initial"/>
+ <xs:enumeration value="translated"/>
+ <xs:enumeration value="reviewed"/>
+ <xs:enumeration value="final"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- Structural Elements -->
+
+ <xs:element name="xliff">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:file"/>
+ </xs:sequence>
+ <xs:attribute name="version" use="required"/>
+ <xs:attribute name="srcLang" use="required"/>
+ <xs:attribute name="trgLang" use="optional"/>
+ <xs:attribute ref="xml:space" use="optional" default="default"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="file">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:skeleton"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
+ <xs:choice minOccurs="1" maxOccurs="unbounded">
+ <xs:element ref="xlf:unit"/>
+ <xs:element ref="xlf:group"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="original" use="optional"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="srcDir" use="optional" type="xlf:dirValue" default="auto"/>
+ <xs:attribute name="trgDir" use="optional" type="xlf:dirValue" default="auto"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="skeleton">
+ <xs:complexType mixed="true">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="href" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="group">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="xlf:unit"/>
+ <xs:element ref="xlf:group"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="name" use="optional"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="srcDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="trgDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="unit">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:originalData"/>
+ <xs:choice minOccurs="1" maxOccurs="unbounded">
+ <xs:element ref="xlf:segment"/>
+ <xs:element ref="xlf:ignorable"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="name" use="optional"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="srcDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="trgDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:attribute name="type" use="optional" type="xlf:userDefinedValue"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="segment">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="1" ref="xlf:source"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:target"/>
+ </xs:sequence>
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="state" use="optional" type="xlf:stateType" default="initial"/>
+ <xs:attribute name="subState" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ignorable">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="1" ref="xlf:source"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:target"/>
+ </xs:sequence>
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="notes">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:note"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="note">
+ <xs:complexType mixed="true">
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="appliesTo" use="optional" type="xlf:appliesTo"/>
+ <xs:attribute name="category" use="optional"/>
+ <xs:attribute name="priority" use="optional" type="xlf:priorityValue" default="1"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="originalData">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:data"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="data">
+ <xs:complexType mixed="true">
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="xlf:cp"/>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue" default="auto"/>
+ <xs:attribute ref="xml:space" use="optional" fixed="preserve"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="source">
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute ref="xml:lang" use="optional"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="target">
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute ref="xml:lang" use="optional"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:attribute name="order" use="optional" type="xs:positiveInteger"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Inline Elements -->
+
+ <xs:element name="cp">
+ <!-- Code Point -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="hex" use="required" type="xs:hexBinary"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ph">
+ <!-- Placeholder -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="disp" use="optional"/>
+ <xs:attribute name="equiv" use="optional"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="pc">
+ <!-- Paired Code -->
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dispEnd" use="optional"/>
+ <xs:attribute name="dispStart" use="optional"/>
+ <xs:attribute name="equivEnd" use="optional"/>
+ <xs:attribute name="equivStart" use="optional"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRefEnd" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRefStart" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="subFlowsEnd" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subFlowsStart" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="sc">
+ <!-- Start Code -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="disp" use="optional"/>
+ <xs:attribute name="equiv" use="optional"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="isolated" use="optional" type="xlf:yesNo" default="no"/>
+ <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ec">
+ <!-- End Code -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="disp" use="optional"/>
+ <xs:attribute name="equiv" use="optional"/>
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="isolated" use="optional" type="xlf:yesNo" default="no"/>
+ <xs:attribute name="startRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="mrk">
+ <!-- Annotation Marker -->
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_typeForMrk"/>
+ <xs:attribute name="ref" use="optional" type="xs:anyURI"/>
+ <xs:attribute name="value" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="sm">
+ <!-- Start Annotation Marker -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_typeForMrk"/>
+ <xs:attribute name="ref" use="optional" type="xs:anyURI"/>
+ <xs:attribute name="value" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="em">
+ <!-- End Annotation Marker -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="startRef" use="required" type="xs:NMTOKEN"/>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xml.xsd b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xml.xsd
new file mode 100644
index 0000000..a46162a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xml.xsd
@@ -0,0 +1,309 @@
+<?xml version='1.0'?>
+<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?>
+<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns ="http://www.w3.org/1999/xhtml"
+ xml:lang="en">
+
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+ <h1>About the XML namespace</h1>
+
+ <div class="bodytext">
+ <p>
+
+ This schema document describes the XML namespace, in a form
+ suitable for import by other schema documents.
+ </p>
+ <p>
+ See <a href="http://www.w3.org/XML/1998/namespace.html">
+ http://www.w3.org/XML/1998/namespace.html</a> and
+ <a href="http://www.w3.org/TR/REC-xml">
+ http://www.w3.org/TR/REC-xml</a> for information
+ about this namespace.
+ </p>
+
+ <p>
+ Note that local names in this namespace are intended to be
+ defined only by the World Wide Web Consortium or its subgroups.
+ The names currently defined in this namespace are listed below.
+ They should not be used with conflicting semantics by any Working
+ Group, specification, or document instance.
+ </p>
+ <p>
+ See further below in this document for more information about <a
+ href="#usage">how to refer to this schema document from your own
+ XSD schema documents</a> and about <a href="#nsversioning">the
+ namespace-versioning policy governing this schema document</a>.
+ </p>
+ </div>
+ </div>
+
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:attribute name="lang">
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>lang (as an attribute name)</h3>
+ <p>
+
+ denotes an attribute whose value
+ is a language code for the natural language of the content of
+ any element; its value is inherited. This name is reserved
+ by virtue of its definition in the XML specification.</p>
+
+ </div>
+ <div>
+ <h4>Notes</h4>
+ <p>
+ Attempting to install the relevant ISO 2- and 3-letter
+ codes as the enumerated possible values is probably never
+ going to be a realistic possibility.
+ </p>
+ <p>
+
+ See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
+ http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a>
+ and the IANA language subtag registry at
+ <a href="http://www.iana.org/assignments/language-subtag-registry">
+ http://www.iana.org/assignments/language-subtag-registry</a>
+ for further information.
+ </p>
+ <p>
+
+ The union allows for the 'un-declaration' of xml:lang with
+ the empty string.
+ </p>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:union memberTypes="xs:language">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value=""/>
+
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="space">
+ <xs:annotation>
+ <xs:documentation>
+
+ <div>
+
+ <h3>space (as an attribute name)</h3>
+ <p>
+ denotes an attribute whose
+ value is a keyword indicating what whitespace processing
+ discipline is intended for the content of the element; its
+ value is inherited. This name is reserved by virtue of its
+ definition in the XML specification.</p>
+
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+
+ <xs:restriction base="xs:NCName">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="preserve"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="base" type="xs:anyURI"> <xs:annotation>
+ <xs:documentation>
+
+ <div>
+
+ <h3>base (as an attribute name)</h3>
+ <p>
+ denotes an attribute whose value
+ provides a URI to be used as the base for interpreting any
+ relative URIs in the scope of the element on which it
+ appears; its value is inherited. This name is reserved
+ by virtue of its definition in the XML Base specification.</p>
+
+ <p>
+ See <a
+ href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a>
+ for information about this attribute.
+ </p>
+
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ <xs:attribute name="id" type="xs:ID">
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>id (as an attribute name)</h3>
+ <p>
+
+ denotes an attribute whose value
+ should be interpreted as if declared to be of type ID.
+ This name is reserved by virtue of its definition in the
+ xml:id specification.</p>
+
+ <p>
+ See <a
+ href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a>
+ for information about this attribute.
+ </p>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ </xs:attribute>
+
+ <xs:attributeGroup name="specialAttrs">
+ <xs:attribute ref="xml:base"/>
+ <xs:attribute ref="xml:lang"/>
+ <xs:attribute ref="xml:space"/>
+ <xs:attribute ref="xml:id"/>
+ </xs:attributeGroup>
+
+ <xs:annotation>
+
+ <xs:documentation>
+ <div>
+
+ <h3>Father (in any context at all)</h3>
+
+ <div class="bodytext">
+ <p>
+ denotes Jon Bosak, the chair of
+ the original XML Working Group. This name is reserved by
+ the following decision of the W3C XML Plenary and
+ XML Coordination groups:
+ </p>
+ <blockquote>
+ <p>
+
+ In appreciation for his vision, leadership and
+ dedication the W3C XML Plenary on this 10th day of
+ February, 2000, reserves for Jon Bosak in perpetuity
+ the XML name "xml:Father".
+ </p>
+ </blockquote>
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>
+
+ <div xml:id="usage" id="usage">
+ <h2><a name="usage">About this schema document</a></h2>
+
+ <div class="bodytext">
+ <p>
+ This schema defines attributes and an attribute group suitable
+ for use by schemas wishing to allow <code>xml:base</code>,
+ <code>xml:lang</code>, <code>xml:space</code> or
+ <code>xml:id</code> attributes on elements they define.
+ </p>
+
+ <p>
+ To enable this, such a schema must import this schema for
+ the XML namespace, e.g. as follows:
+ </p>
+ <pre>
+ <schema.. .>
+ .. .
+ <import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ </pre>
+ <p>
+ or
+ </p>
+ <pre>
+
+ <import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+ </pre>
+ <p>
+ Subsequently, qualified reference to any of the attributes or the
+ group defined below will have the desired effect, e.g.
+ </p>
+ <pre>
+ <type.. .>
+ .. .
+ <attributeGroup ref="xml:specialAttrs"/>
+ </pre>
+ <p>
+ will define a type which will schema-validate an instance element
+ with any of those attributes.
+ </p>
+
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>
+ <div id="nsversioning" xml:id="nsversioning">
+ <h2><a name="nsversioning">Versioning policy for this schema document</a></h2>
+
+ <div class="bodytext">
+ <p>
+ In keeping with the XML Schema WG's standard versioning
+ policy, this schema document will persist at
+ <a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd</a>.
+ </p>
+ <p>
+ At the date of issue it can also be found at
+ <a href="http://www.w3.org/2001/xml.xsd">
+ http://www.w3.org/2001/xml.xsd</a>.
+ </p>
+
+ <p>
+ The schema document at that URI may however change in the future,
+ in order to remain compatible with the latest version of XML
+ Schema itself, or with the XML namespace itself. In other words,
+ if the XML Schema or XML namespaces change, the version of this
+ document at <a href="http://www.w3.org/2001/xml.xsd">
+ http://www.w3.org/2001/xml.xsd
+ </a>
+ will change accordingly; the version at
+ <a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd
+ </a>
+ will not change.
+ </p>
+ <p>
+
+ Previous dated (and unchanging) versions of this schema
+ document are at:
+ </p>
+ <ul>
+ <li><a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2007/08/xml.xsd">
+ http://www.w3.org/2007/08/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2004/10/xml.xsd">
+
+ http://www.w3.org/2004/10/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2001/03/xml.xsd">
+ http://www.w3.org/2001/03/xml.xsd</a></li>
+ </ul>
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+</xs:schema>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderFactoryTestCase.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderFactoryTestCase.php
new file mode 100644
index 0000000..6d5f4b7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderFactoryTestCase.php
@@ -0,0 +1,147 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Test;
+
+use PHPUnit\Framework\TestCase;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpClient\MockHttpClient;
+use Symfony\Component\Translation\Dumper\XliffFileDumper;
+use Symfony\Component\Translation\Exception\IncompleteDsnException;
+use Symfony\Component\Translation\Exception\UnsupportedSchemeException;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\Provider\Dsn;
+use Symfony\Component\Translation\Provider\ProviderFactoryInterface;
+use Symfony\Contracts\HttpClient\HttpClientInterface;
+
+/**
+ * A test case to ease testing a translation provider factory.
+ *
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @internal
+ */
+abstract class ProviderFactoryTestCase extends TestCase
+{
+ protected $client;
+ protected $logger;
+ protected $defaultLocale;
+ protected $loader;
+ protected $xliffFileDumper;
+
+ abstract public function createFactory(): ProviderFactoryInterface;
+
+ /**
+ * @return iterable<array{0: bool, 1: string}>
+ */
+ abstract public function supportsProvider(): iterable;
+
+ /**
+ * @return iterable<array{0: string, 1: string, 2: TransportInterface}>
+ */
+ abstract public function createProvider(): iterable;
+
+ /**
+ * @return iterable<array{0: string, 1: string|null}>
+ */
+ public function unsupportedSchemeProvider(): iterable
+ {
+ return [];
+ }
+
+ /**
+ * @return iterable<array{0: string, 1: string|null}>
+ */
+ public function incompleteDsnProvider(): iterable
+ {
+ return [];
+ }
+
+ /**
+ * @dataProvider supportsProvider
+ */
+ public function testSupports(bool $expected, string $dsn)
+ {
+ $factory = $this->createFactory();
+
+ $this->assertSame($expected, $factory->supports(new Dsn($dsn)));
+ }
+
+ /**
+ * @dataProvider createProvider
+ */
+ public function testCreate(string $expected, string $dsn)
+ {
+ $factory = $this->createFactory();
+ $provider = $factory->create(new Dsn($dsn));
+
+ $this->assertSame($expected, (string) $provider);
+ }
+
+ /**
+ * @dataProvider unsupportedSchemeProvider
+ */
+ public function testUnsupportedSchemeException(string $dsn, string $message = null)
+ {
+ $factory = $this->createFactory();
+
+ $dsn = new Dsn($dsn);
+
+ $this->expectException(UnsupportedSchemeException::class);
+ if (null !== $message) {
+ $this->expectExceptionMessage($message);
+ }
+
+ $factory->create($dsn);
+ }
+
+ /**
+ * @dataProvider incompleteDsnProvider
+ */
+ public function testIncompleteDsnException(string $dsn, string $message = null)
+ {
+ $factory = $this->createFactory();
+
+ $dsn = new Dsn($dsn);
+
+ $this->expectException(IncompleteDsnException::class);
+ if (null !== $message) {
+ $this->expectExceptionMessage($message);
+ }
+
+ $factory->create($dsn);
+ }
+
+ protected function getClient(): HttpClientInterface
+ {
+ return $this->client ?? $this->client = new MockHttpClient();
+ }
+
+ protected function getLogger(): LoggerInterface
+ {
+ return $this->logger ?? $this->logger = $this->createMock(LoggerInterface::class);
+ }
+
+ protected function getDefaultLocale(): string
+ {
+ return $this->defaultLocale ?? $this->defaultLocale = 'en';
+ }
+
+ protected function getLoader(): LoaderInterface
+ {
+ return $this->loader ?? $this->loader = $this->createMock(LoaderInterface::class);
+ }
+
+ protected function getXliffFileDumper(): XliffFileDumper
+ {
+ return $this->xliffFileDumper ?? $this->xliffFileDumper = $this->createMock(XliffFileDumper::class);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderTestCase.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderTestCase.php
new file mode 100644
index 0000000..238fd96
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderTestCase.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Test;
+
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpClient\MockHttpClient;
+use Symfony\Component\Translation\Dumper\XliffFileDumper;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\Provider\ProviderInterface;
+use Symfony\Contracts\HttpClient\HttpClientInterface;
+
+/**
+ * A test case to ease testing a translation provider.
+ *
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @internal
+ */
+abstract class ProviderTestCase extends TestCase
+{
+ protected $client;
+ protected $logger;
+ protected $defaultLocale;
+ protected $loader;
+ protected $xliffFileDumper;
+
+ abstract public function createProvider(HttpClientInterface $client, LoaderInterface $loader, LoggerInterface $logger, string $defaultLocale, string $endpoint): ProviderInterface;
+
+ /**
+ * @return iterable<array{0: string, 1: ProviderInterface}>
+ */
+ abstract public function toStringProvider(): iterable;
+
+ /**
+ * @dataProvider toStringProvider
+ */
+ public function testToString(ProviderInterface $provider, string $expected)
+ {
+ $this->assertSame($expected, (string) $provider);
+ }
+
+ protected function getClient(): MockHttpClient
+ {
+ return $this->client ?? $this->client = new MockHttpClient();
+ }
+
+ /**
+ * @return LoaderInterface&MockObject
+ */
+ protected function getLoader(): LoaderInterface
+ {
+ return $this->loader ?? $this->loader = $this->createMock(LoaderInterface::class);
+ }
+
+ /**
+ * @return LoaderInterface&MockObject
+ */
+ protected function getLogger(): LoggerInterface
+ {
+ return $this->logger ?? $this->logger = $this->createMock(LoggerInterface::class);
+ }
+
+ protected function getDefaultLocale(): string
+ {
+ return $this->defaultLocale ?? $this->defaultLocale = 'en';
+ }
+
+ /**
+ * @return LoaderInterface&MockObject
+ */
+ protected function getXliffFileDumper(): XliffFileDumper
+ {
+ return $this->xliffFileDumper ?? $this->xliffFileDumper = $this->createMock(XliffFileDumper::class);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatableMessage.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatableMessage.php
new file mode 100644
index 0000000..82ae6d7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatableMessage.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Contracts\Translation\TranslatableInterface;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+/**
+ * @author Nate Wiebe <nate@northern.co>
+ */
+class TranslatableMessage implements TranslatableInterface
+{
+ private $message;
+ private $parameters;
+ private $domain;
+
+ public function __construct(string $message, array $parameters = [], string $domain = null)
+ {
+ $this->message = $message;
+ $this->parameters = $parameters;
+ $this->domain = $domain;
+ }
+
+ public function __toString(): string
+ {
+ return $this->getMessage();
+ }
+
+ public function getMessage(): string
+ {
+ return $this->message;
+ }
+
+ public function getParameters(): array
+ {
+ return $this->parameters;
+ }
+
+ public function getDomain(): ?string
+ {
+ return $this->domain;
+ }
+
+ public function trans(TranslatorInterface $translator, string $locale = null): string
+ {
+ return $translator->trans($this->getMessage(), $this->getParameters(), $this->getDomain(), $locale);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Translator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Translator.php
new file mode 100644
index 0000000..9a63956
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Translator.php
@@ -0,0 +1,490 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Config\ConfigCacheFactory;
+use Symfony\Component\Config\ConfigCacheFactoryInterface;
+use Symfony\Component\Config\ConfigCacheInterface;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\Formatter\IntlFormatterInterface;
+use Symfony\Component\Translation\Formatter\MessageFormatter;
+use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Contracts\Translation\LocaleAwareInterface;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(MessageCatalogue::class);
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface
+{
+ /**
+ * @var MessageCatalogueInterface[]
+ */
+ protected $catalogues = [];
+
+ /**
+ * @var string
+ */
+ private $locale;
+
+ /**
+ * @var array
+ */
+ private $fallbackLocales = [];
+
+ /**
+ * @var LoaderInterface[]
+ */
+ private $loaders = [];
+
+ /**
+ * @var array
+ */
+ private $resources = [];
+
+ /**
+ * @var MessageFormatterInterface
+ */
+ private $formatter;
+
+ /**
+ * @var string
+ */
+ private $cacheDir;
+
+ /**
+ * @var bool
+ */
+ private $debug;
+
+ private $cacheVary;
+
+ /**
+ * @var ConfigCacheFactoryInterface|null
+ */
+ private $configCacheFactory;
+
+ /**
+ * @var array|null
+ */
+ private $parentLocales;
+
+ private $hasIntlFormatter;
+
+ /**
+ * @throws InvalidArgumentException If a locale contains invalid characters
+ */
+ public function __construct(string $locale, MessageFormatterInterface $formatter = null, string $cacheDir = null, bool $debug = false, array $cacheVary = [])
+ {
+ $this->setLocale($locale);
+
+ if (null === $formatter) {
+ $formatter = new MessageFormatter();
+ }
+
+ $this->formatter = $formatter;
+ $this->cacheDir = $cacheDir;
+ $this->debug = $debug;
+ $this->cacheVary = $cacheVary;
+ $this->hasIntlFormatter = $formatter instanceof IntlFormatterInterface;
+ }
+
+ public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
+ {
+ $this->configCacheFactory = $configCacheFactory;
+ }
+
+ /**
+ * Adds a Loader.
+ *
+ * @param string $format The name of the loader (@see addResource())
+ */
+ public function addLoader(string $format, LoaderInterface $loader)
+ {
+ $this->loaders[$format] = $loader;
+ }
+
+ /**
+ * Adds a Resource.
+ *
+ * @param string $format The name of the loader (@see addLoader())
+ * @param mixed $resource The resource name
+ *
+ * @throws InvalidArgumentException If the locale contains invalid characters
+ */
+ public function addResource(string $format, $resource, string $locale, string $domain = null)
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $this->assertValidLocale($locale);
+ $locale ?: $locale = class_exists(\Locale::class) ? \Locale::getDefault() : 'en';
+
+ $this->resources[$locale][] = [$format, $resource, $domain];
+
+ if (\in_array($locale, $this->fallbackLocales)) {
+ $this->catalogues = [];
+ } else {
+ unset($this->catalogues[$locale]);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale(string $locale)
+ {
+ $this->assertValidLocale($locale);
+ $this->locale = $locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
+ }
+
+ /**
+ * Sets the fallback locales.
+ *
+ * @throws InvalidArgumentException If a locale contains invalid characters
+ */
+ public function setFallbackLocales(array $locales)
+ {
+ // needed as the fallback locales are linked to the already loaded catalogues
+ $this->catalogues = [];
+
+ foreach ($locales as $locale) {
+ $this->assertValidLocale($locale);
+ }
+
+ $this->fallbackLocales = $this->cacheVary['fallback_locales'] = $locales;
+ }
+
+ /**
+ * Gets the fallback locales.
+ *
+ * @internal
+ */
+ public function getFallbackLocales(): array
+ {
+ return $this->fallbackLocales;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null)
+ {
+ if (null === $id || '' === $id) {
+ return '';
+ }
+
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $catalogue = $this->getCatalogue($locale);
+ $locale = $catalogue->getLocale();
+ while (!$catalogue->defines($id, $domain)) {
+ if ($cat = $catalogue->getFallbackCatalogue()) {
+ $catalogue = $cat;
+ $locale = $catalogue->getLocale();
+ } else {
+ break;
+ }
+ }
+
+ $len = \strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX);
+ if ($this->hasIntlFormatter
+ && ($catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)
+ || (\strlen($domain) > $len && 0 === substr_compare($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX, -$len, $len)))
+ ) {
+ return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, $parameters);
+ }
+
+ return $this->formatter->format($catalogue->get($id, $domain), $locale, $parameters);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue(string $locale = null)
+ {
+ if (!$locale) {
+ $locale = $this->getLocale();
+ } else {
+ $this->assertValidLocale($locale);
+ }
+
+ if (!isset($this->catalogues[$locale])) {
+ $this->loadCatalogue($locale);
+ }
+
+ return $this->catalogues[$locale];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogues(): array
+ {
+ return array_values($this->catalogues);
+ }
+
+ /**
+ * Gets the loaders.
+ *
+ * @return array LoaderInterface[]
+ */
+ protected function getLoaders()
+ {
+ return $this->loaders;
+ }
+
+ protected function loadCatalogue(string $locale)
+ {
+ if (null === $this->cacheDir) {
+ $this->initializeCatalogue($locale);
+ } else {
+ $this->initializeCacheCatalogue($locale);
+ }
+ }
+
+ protected function initializeCatalogue(string $locale)
+ {
+ $this->assertValidLocale($locale);
+
+ try {
+ $this->doLoadCatalogue($locale);
+ } catch (NotFoundResourceException $e) {
+ if (!$this->computeFallbackLocales($locale)) {
+ throw $e;
+ }
+ }
+ $this->loadFallbackCatalogues($locale);
+ }
+
+ private function initializeCacheCatalogue(string $locale): void
+ {
+ if (isset($this->catalogues[$locale])) {
+ /* Catalogue already initialized. */
+ return;
+ }
+
+ $this->assertValidLocale($locale);
+ $cache = $this->getConfigCacheFactory()->cache($this->getCatalogueCachePath($locale),
+ function (ConfigCacheInterface $cache) use ($locale) {
+ $this->dumpCatalogue($locale, $cache);
+ }
+ );
+
+ if (isset($this->catalogues[$locale])) {
+ /* Catalogue has been initialized as it was written out to cache. */
+ return;
+ }
+
+ /* Read catalogue from cache. */
+ $this->catalogues[$locale] = include $cache->getPath();
+ }
+
+ private function dumpCatalogue(string $locale, ConfigCacheInterface $cache): void
+ {
+ $this->initializeCatalogue($locale);
+ $fallbackContent = $this->getFallbackContent($this->catalogues[$locale]);
+
+ $content = sprintf(<<<EOF
+<?php
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+\$catalogue = new MessageCatalogue('%s', %s);
+
+%s
+return \$catalogue;
+
+EOF
+ ,
+ $locale,
+ var_export($this->getAllMessages($this->catalogues[$locale]), true),
+ $fallbackContent
+ );
+
+ $cache->write($content, $this->catalogues[$locale]->getResources());
+ }
+
+ private function getFallbackContent(MessageCatalogue $catalogue): string
+ {
+ $fallbackContent = '';
+ $current = '';
+ $replacementPattern = '/[^a-z0-9_]/i';
+ $fallbackCatalogue = $catalogue->getFallbackCatalogue();
+ while ($fallbackCatalogue) {
+ $fallback = $fallbackCatalogue->getLocale();
+ $fallbackSuffix = ucfirst(preg_replace($replacementPattern, '_', $fallback));
+ $currentSuffix = ucfirst(preg_replace($replacementPattern, '_', $current));
+
+ $fallbackContent .= sprintf(<<<'EOF'
+$catalogue%s = new MessageCatalogue('%s', %s);
+$catalogue%s->addFallbackCatalogue($catalogue%s);
+
+EOF
+ ,
+ $fallbackSuffix,
+ $fallback,
+ var_export($this->getAllMessages($fallbackCatalogue), true),
+ $currentSuffix,
+ $fallbackSuffix
+ );
+ $current = $fallbackCatalogue->getLocale();
+ $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
+ }
+
+ return $fallbackContent;
+ }
+
+ private function getCatalogueCachePath(string $locale): string
+ {
+ return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('sha256', serialize($this->cacheVary), true)), 0, 7), '/', '_').'.php';
+ }
+
+ /**
+ * @internal
+ */
+ protected function doLoadCatalogue(string $locale): void
+ {
+ $this->catalogues[$locale] = new MessageCatalogue($locale);
+
+ if (isset($this->resources[$locale])) {
+ foreach ($this->resources[$locale] as $resource) {
+ if (!isset($this->loaders[$resource[0]])) {
+ if (\is_string($resource[1])) {
+ throw new RuntimeException(sprintf('No loader is registered for the "%s" format when loading the "%s" resource.', $resource[0], $resource[1]));
+ }
+
+ throw new RuntimeException(sprintf('No loader is registered for the "%s" format.', $resource[0]));
+ }
+ $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
+ }
+ }
+ }
+
+ private function loadFallbackCatalogues(string $locale): void
+ {
+ $current = $this->catalogues[$locale];
+
+ foreach ($this->computeFallbackLocales($locale) as $fallback) {
+ if (!isset($this->catalogues[$fallback])) {
+ $this->initializeCatalogue($fallback);
+ }
+
+ $fallbackCatalogue = new MessageCatalogue($fallback, $this->getAllMessages($this->catalogues[$fallback]));
+ foreach ($this->catalogues[$fallback]->getResources() as $resource) {
+ $fallbackCatalogue->addResource($resource);
+ }
+ $current->addFallbackCatalogue($fallbackCatalogue);
+ $current = $fallbackCatalogue;
+ }
+ }
+
+ protected function computeFallbackLocales(string $locale)
+ {
+ if (null === $this->parentLocales) {
+ $this->parentLocales = json_decode(file_get_contents(__DIR__.'/Resources/data/parents.json'), true);
+ }
+
+ $locales = [];
+ foreach ($this->fallbackLocales as $fallback) {
+ if ($fallback === $locale) {
+ continue;
+ }
+
+ $locales[] = $fallback;
+ }
+
+ while ($locale) {
+ $parent = $this->parentLocales[$locale] ?? null;
+
+ if ($parent) {
+ $locale = 'root' !== $parent ? $parent : null;
+ } elseif (\function_exists('locale_parse')) {
+ $localeSubTags = locale_parse($locale);
+ $locale = null;
+ if (1 < \count($localeSubTags)) {
+ array_pop($localeSubTags);
+ $locale = locale_compose($localeSubTags) ?: null;
+ }
+ } elseif ($i = strrpos($locale, '_') ?: strrpos($locale, '-')) {
+ $locale = substr($locale, 0, $i);
+ } else {
+ $locale = null;
+ }
+
+ if (null !== $locale) {
+ array_unshift($locales, $locale);
+ }
+ }
+
+ return array_unique($locales);
+ }
+
+ /**
+ * Asserts that the locale is valid, throws an Exception if not.
+ *
+ * @throws InvalidArgumentException If the locale contains invalid characters
+ */
+ protected function assertValidLocale(string $locale)
+ {
+ if (!preg_match('/^[a-z0-9@_\\.\\-]*$/i', (string) $locale)) {
+ throw new InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale));
+ }
+ }
+
+ /**
+ * Provides the ConfigCache factory implementation, falling back to a
+ * default implementation if necessary.
+ */
+ private function getConfigCacheFactory(): ConfigCacheFactoryInterface
+ {
+ if (!$this->configCacheFactory) {
+ $this->configCacheFactory = new ConfigCacheFactory($this->debug);
+ }
+
+ return $this->configCacheFactory;
+ }
+
+ private function getAllMessages(MessageCatalogueInterface $catalogue): array
+ {
+ $allMessages = [];
+
+ foreach ($catalogue->all() as $domain => $messages) {
+ if ($intlMessages = $catalogue->all($domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
+ $allMessages[$domain.MessageCatalogue::INTL_DOMAIN_SUFFIX] = $intlMessages;
+ $messages = array_diff_key($messages, $intlMessages);
+ }
+ if ($messages) {
+ $allMessages[$domain] = $messages;
+ }
+ }
+
+ return $allMessages;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBag.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBag.php
new file mode 100644
index 0000000..c655578
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBag.php
@@ -0,0 +1,105 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Translation\Catalogue\AbstractOperation;
+use Symfony\Component\Translation\Catalogue\TargetOperation;
+
+final class TranslatorBag implements TranslatorBagInterface
+{
+ /** @var MessageCatalogue[] */
+ private $catalogues = [];
+
+ public function addCatalogue(MessageCatalogue $catalogue): void
+ {
+ if (null !== $existingCatalogue = $this->getCatalogue($catalogue->getLocale())) {
+ $catalogue->addCatalogue($existingCatalogue);
+ }
+
+ $this->catalogues[$catalogue->getLocale()] = $catalogue;
+ }
+
+ public function addBag(TranslatorBagInterface $bag): void
+ {
+ foreach ($bag->getCatalogues() as $catalogue) {
+ $this->addCatalogue($catalogue);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue(string $locale = null)
+ {
+ if (null === $locale || !isset($this->catalogues[$locale])) {
+ $this->catalogues[$locale] = new MessageCatalogue($locale);
+ }
+
+ return $this->catalogues[$locale];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogues(): array
+ {
+ return array_values($this->catalogues);
+ }
+
+ public function diff(TranslatorBagInterface $diffBag): self
+ {
+ $diff = new self();
+
+ foreach ($this->catalogues as $locale => $catalogue) {
+ if (null === $diffCatalogue = $diffBag->getCatalogue($locale)) {
+ $diff->addCatalogue($catalogue);
+
+ continue;
+ }
+
+ $operation = new TargetOperation($diffCatalogue, $catalogue);
+ $operation->moveMessagesToIntlDomainsIfPossible(AbstractOperation::NEW_BATCH);
+ $newCatalogue = new MessageCatalogue($locale);
+
+ foreach ($operation->getDomains() as $domain) {
+ $newCatalogue->add($operation->getNewMessages($domain), $domain);
+ }
+
+ $diff->addCatalogue($newCatalogue);
+ }
+
+ return $diff;
+ }
+
+ public function intersect(TranslatorBagInterface $intersectBag): self
+ {
+ $diff = new self();
+
+ foreach ($this->catalogues as $locale => $catalogue) {
+ if (null === $intersectCatalogue = $intersectBag->getCatalogue($locale)) {
+ continue;
+ }
+
+ $operation = new TargetOperation($catalogue, $intersectCatalogue);
+ $operation->moveMessagesToIntlDomainsIfPossible(AbstractOperation::OBSOLETE_BATCH);
+ $obsoleteCatalogue = new MessageCatalogue($locale);
+
+ foreach ($operation->getDomains() as $domain) {
+ $obsoleteCatalogue->add($operation->getObsoleteMessages($domain), $domain);
+ }
+
+ $diff->addCatalogue($obsoleteCatalogue);
+ }
+
+ return $diff;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBagInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBagInterface.php
new file mode 100644
index 0000000..4228977
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBagInterface.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+
+/**
+ * TranslatorBagInterface.
+ *
+ * @method MessageCatalogueInterface[] getCatalogues() Returns all catalogues of the instance
+ *
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+interface TranslatorBagInterface
+{
+ /**
+ * Gets the catalogue by locale.
+ *
+ * @param string|null $locale The locale or null to use the default
+ *
+ * @return MessageCatalogueInterface
+ *
+ * @throws InvalidArgumentException If the locale contains invalid characters
+ */
+ public function getCatalogue(string $locale = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/ArrayConverter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/ArrayConverter.php
new file mode 100644
index 0000000..acfbfc3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/ArrayConverter.php
@@ -0,0 +1,99 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Util;
+
+/**
+ * ArrayConverter generates tree like structure from a message catalogue.
+ * e.g. this
+ * 'foo.bar1' => 'test1',
+ * 'foo.bar2' => 'test2'
+ * converts to follows:
+ * foo:
+ * bar1: test1
+ * bar2: test2.
+ *
+ * @author Gennady Telegin <gtelegin@gmail.com>
+ */
+class ArrayConverter
+{
+ /**
+ * Converts linear messages array to tree-like array.
+ * For example this array('foo.bar' => 'value') will be converted to ['foo' => ['bar' => 'value']].
+ *
+ * @param array $messages Linear messages array
+ *
+ * @return array Tree-like messages array
+ */
+ public static function expandToTree(array $messages)
+ {
+ $tree = [];
+
+ foreach ($messages as $id => $value) {
+ $referenceToElement = &self::getElementByPath($tree, explode('.', $id));
+
+ $referenceToElement = $value;
+
+ unset($referenceToElement);
+ }
+
+ return $tree;
+ }
+
+ private static function &getElementByPath(array &$tree, array $parts)
+ {
+ $elem = &$tree;
+ $parentOfElem = null;
+
+ foreach ($parts as $i => $part) {
+ if (isset($elem[$part]) && \is_string($elem[$part])) {
+ /* Process next case:
+ * 'foo': 'test1',
+ * 'foo.bar': 'test2'
+ *
+ * $tree['foo'] was string before we found array {bar: test2}.
+ * Treat new element as string too, e.g. add $tree['foo.bar'] = 'test2';
+ */
+ $elem = &$elem[implode('.', \array_slice($parts, $i))];
+ break;
+ }
+ $parentOfElem = &$elem;
+ $elem = &$elem[$part];
+ }
+
+ if ($elem && \is_array($elem) && $parentOfElem) {
+ /* Process next case:
+ * 'foo.bar': 'test1'
+ * 'foo': 'test2'
+ *
+ * $tree['foo'] was array = {bar: 'test1'} before we found string constant `foo`.
+ * Cancel treating $tree['foo'] as array and cancel back it expansion,
+ * e.g. make it $tree['foo.bar'] = 'test1' again.
+ */
+ self::cancelExpand($parentOfElem, $part, $elem);
+ }
+
+ return $elem;
+ }
+
+ private static function cancelExpand(array &$tree, string $prefix, array $node)
+ {
+ $prefix .= '.';
+
+ foreach ($node as $id => $value) {
+ if (\is_string($value)) {
+ $tree[$prefix.$id] = $value;
+ } else {
+ self::cancelExpand($tree, $prefix.$id, $value);
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/XliffUtils.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/XliffUtils.php
new file mode 100644
index 0000000..e4373a7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/XliffUtils.php
@@ -0,0 +1,196 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Util;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+
+/**
+ * Provides some utility methods for XLIFF translation files, such as validating
+ * their contents according to the XSD schema.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class XliffUtils
+{
+ /**
+ * Gets xliff file version based on the root "version" attribute.
+ *
+ * Defaults to 1.2 for backwards compatibility.
+ *
+ * @throws InvalidArgumentException
+ */
+ public static function getVersionNumber(\DOMDocument $dom): string
+ {
+ /** @var \DOMNode $xliff */
+ foreach ($dom->getElementsByTagName('xliff') as $xliff) {
+ $version = $xliff->attributes->getNamedItem('version');
+ if ($version) {
+ return $version->nodeValue;
+ }
+
+ $namespace = $xliff->attributes->getNamedItem('xmlns');
+ if ($namespace) {
+ if (0 !== substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34)) {
+ throw new InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s".', $namespace));
+ }
+
+ return substr($namespace, 34);
+ }
+ }
+
+ // Falls back to v1.2
+ return '1.2';
+ }
+
+ /**
+ * Validates and parses the given file into a DOMDocument.
+ *
+ * @throws InvalidResourceException
+ */
+ public static function validateSchema(\DOMDocument $dom): array
+ {
+ $xliffVersion = static::getVersionNumber($dom);
+ $internalErrors = libxml_use_internal_errors(true);
+ if ($shouldEnable = self::shouldEnableEntityLoader()) {
+ $disableEntities = libxml_disable_entity_loader(false);
+ }
+ try {
+ $isValid = @$dom->schemaValidateSource(self::getSchema($xliffVersion));
+ if (!$isValid) {
+ return self::getXmlErrors($internalErrors);
+ }
+ } finally {
+ if ($shouldEnable) {
+ libxml_disable_entity_loader($disableEntities);
+ }
+ }
+
+ $dom->normalizeDocument();
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($internalErrors);
+
+ return [];
+ }
+
+ private static function shouldEnableEntityLoader(): bool
+ {
+ // Version prior to 8.0 can be enabled without deprecation
+ if (\PHP_VERSION_ID < 80000) {
+ return true;
+ }
+
+ static $dom, $schema;
+ if (null === $dom) {
+ $dom = new \DOMDocument();
+ $dom->loadXML('<?xml version="1.0"?><test/>');
+
+ $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
+ register_shutdown_function(static function () use ($tmpfile) {
+ @unlink($tmpfile);
+ });
+ $schema = '<?xml version="1.0" encoding="utf-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <xsd:include schemaLocation="file:///'.str_replace('\\', '/', $tmpfile).'" />
+</xsd:schema>';
+ file_put_contents($tmpfile, '<?xml version="1.0" encoding="utf-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <xsd:element name="test" type="testType" />
+ <xsd:complexType name="testType"/>
+</xsd:schema>');
+ }
+
+ return !@$dom->schemaValidateSource($schema);
+ }
+
+ public static function getErrorsAsString(array $xmlErrors): string
+ {
+ $errorsAsString = '';
+
+ foreach ($xmlErrors as $error) {
+ $errorsAsString .= sprintf("[%s %s] %s (in %s - line %d, column %d)\n",
+ \LIBXML_ERR_WARNING === $error['level'] ? 'WARNING' : 'ERROR',
+ $error['code'],
+ $error['message'],
+ $error['file'],
+ $error['line'],
+ $error['column']
+ );
+ }
+
+ return $errorsAsString;
+ }
+
+ private static function getSchema(string $xliffVersion): string
+ {
+ if ('1.2' === $xliffVersion) {
+ $schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-1.2-strict.xsd');
+ $xmlUri = 'http://www.w3.org/2001/xml.xsd';
+ } elseif ('2.0' === $xliffVersion) {
+ $schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-2.0.xsd');
+ $xmlUri = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd';
+ } else {
+ throw new InvalidArgumentException(sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion));
+ }
+
+ return self::fixXmlLocation($schemaSource, $xmlUri);
+ }
+
+ /**
+ * Internally changes the URI of a dependent xsd to be loaded locally.
+ */
+ private static function fixXmlLocation(string $schemaSource, string $xmlUri): string
+ {
+ $newPath = str_replace('\\', '/', __DIR__).'/../Resources/schemas/xml.xsd';
+ $parts = explode('/', $newPath);
+ $locationstart = 'file:///';
+ if (0 === stripos($newPath, 'phar://')) {
+ $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
+ if ($tmpfile) {
+ copy($newPath, $tmpfile);
+ $parts = explode('/', str_replace('\\', '/', $tmpfile));
+ } else {
+ array_shift($parts);
+ $locationstart = 'phar:///';
+ }
+ }
+
+ $drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
+ $newPath = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts));
+
+ return str_replace($xmlUri, $newPath, $schemaSource);
+ }
+
+ /**
+ * Returns the XML errors of the internal XML parser.
+ */
+ private static function getXmlErrors(bool $internalErrors): array
+ {
+ $errors = [];
+ foreach (libxml_get_errors() as $error) {
+ $errors[] = [
+ 'level' => \LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
+ 'code' => $error->code,
+ 'message' => trim($error->message),
+ 'file' => $error->file ?: 'n/a',
+ 'line' => $error->line,
+ 'column' => $error->column,
+ ];
+ }
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($internalErrors);
+
+ return $errors;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriter.php
new file mode 100644
index 0000000..0a349b8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriter.php
@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Writer;
+
+use Symfony\Component\Translation\Dumper\DumperInterface;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationWriter writes translation messages.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class TranslationWriter implements TranslationWriterInterface
+{
+ private $dumpers = [];
+
+ /**
+ * Adds a dumper to the writer.
+ */
+ public function addDumper(string $format, DumperInterface $dumper)
+ {
+ $this->dumpers[$format] = $dumper;
+ }
+
+ /**
+ * Obtains the list of supported formats.
+ *
+ * @return array
+ */
+ public function getFormats()
+ {
+ return array_keys($this->dumpers);
+ }
+
+ /**
+ * Writes translation from the catalogue according to the selected format.
+ *
+ * @param string $format The format to use to dump the messages
+ * @param array $options Options that are passed to the dumper
+ *
+ * @throws InvalidArgumentException
+ */
+ public function write(MessageCatalogue $catalogue, string $format, array $options = [])
+ {
+ if (!isset($this->dumpers[$format])) {
+ throw new InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format));
+ }
+
+ // get the right dumper
+ $dumper = $this->dumpers[$format];
+
+ if (isset($options['path']) && !is_dir($options['path']) && !@mkdir($options['path'], 0777, true) && !is_dir($options['path'])) {
+ throw new RuntimeException(sprintf('Translation Writer was not able to create directory "%s".', $options['path']));
+ }
+
+ // save
+ $dumper->dump($catalogue, $options);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriterInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriterInterface.php
new file mode 100644
index 0000000..4321309
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriterInterface.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Writer;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationWriter writes translation messages.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+interface TranslationWriterInterface
+{
+ /**
+ * Writes translation from the catalogue according to the selected format.
+ *
+ * @param string $format The format to use to dump the messages
+ * @param array $options Options that are passed to the dumper
+ *
+ * @throws InvalidArgumentException
+ */
+ public function write(MessageCatalogue $catalogue, string $format, array $options = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/composer.json
new file mode 100644
index 0000000..de84e16
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/composer.json
@@ -0,0 +1,60 @@
+{
+ "name": "symfony/translation",
+ "type": "library",
+ "description": "Provides tools to internationalize your application",
+ "keywords": [],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/translation-contracts": "^2.3"
+ },
+ "require-dev": {
+ "symfony/config": "^4.4|^5.0",
+ "symfony/console": "^4.4|^5.0",
+ "symfony/dependency-injection": "^5.0",
+ "symfony/http-kernel": "^5.0",
+ "symfony/intl": "^4.4|^5.0",
+ "symfony/polyfill-intl-icu": "^1.21",
+ "symfony/service-contracts": "^1.1.2|^2",
+ "symfony/yaml": "^4.4|^5.0",
+ "symfony/finder": "^4.4|^5.0",
+ "psr/log": "^1|^2|^3"
+ },
+ "conflict": {
+ "symfony/config": "<4.4",
+ "symfony/dependency-injection": "<5.0",
+ "symfony/http-kernel": "<5.0",
+ "symfony/twig-bundle": "<5.0",
+ "symfony/yaml": "<4.4"
+ },
+ "provide": {
+ "symfony/translation-implementation": "2.3"
+ },
+ "suggest": {
+ "symfony/config": "",
+ "symfony/yaml": "",
+ "psr/log-implementation": "To use logging capability in translator"
+ },
+ "autoload": {
+ "files": [ "Resources/functions.php" ],
+ "psr-4": { "Symfony\\Component\\Translation\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "minimum-stability": "dev"
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/CHANGELOG.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/CHANGELOG.md
new file mode 100644
index 0000000..f3956e6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/CHANGELOG.md
@@ -0,0 +1,65 @@
+CHANGELOG
+=========
+
+5.2.0
+-----
+
+ * added support for PHPUnit `--colors` option
+ * added `VAR_DUMPER_FORMAT=server` env var value support
+ * prevent replacing the handler when the `VAR_DUMPER_FORMAT` env var is set
+
+5.1.0
+-----
+
+ * added `RdKafka` support
+
+4.4.0
+-----
+
+ * added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()`
+ to configure casters & flags to use in tests
+ * added `ImagineCaster` and infrastructure to dump images
+ * added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data
+ * added `UuidCaster`
+ * made all casters final
+ * added support for the `NO_COLOR` env var (https://no-color.org/)
+
+4.3.0
+-----
+
+ * added `DsCaster` to support dumping the contents of data structures from the Ds extension
+
+4.2.0
+-----
+
+ * support selecting the format to use by setting the environment variable `VAR_DUMPER_FORMAT` to `html` or `cli`
+
+4.1.0
+-----
+
+ * added a `ServerDumper` to send serialized Data clones to a server
+ * added a `ServerDumpCommand` and `DumpServer` to run a server collecting
+ and displaying dumps on a single place with multiple formats support
+ * added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` CLI and HTML formats support
+
+4.0.0
+-----
+
+ * support for passing `\ReflectionClass` instances to the `Caster::castObject()`
+ method has been dropped, pass class names as strings instead
+ * the `Data::getRawData()` method has been removed
+ * the `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$filter = 0`
+ argument and moves `$message = ''` argument at 4th position.
+ * the `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$filter = 0`
+ argument and moves `$message = ''` argument at 4th position.
+
+3.4.0
+-----
+
+ * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth
+ * deprecated `MongoCaster`
+
+2.7.0
+-----
+
+ * deprecated `Cloner\Data::getLimitedClone()`. Use `withMaxDepth`, `withMaxItemsPerDepth` or `withRefHandles` instead.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/AmqpCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/AmqpCaster.php
new file mode 100644
index 0000000..dc3b621
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/AmqpCaster.php
@@ -0,0 +1,212 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts Amqp related classes to array representation.
+ *
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ *
+ * @final
+ */
+class AmqpCaster
+{
+ private const FLAGS = [
+ \AMQP_DURABLE => 'AMQP_DURABLE',
+ \AMQP_PASSIVE => 'AMQP_PASSIVE',
+ \AMQP_EXCLUSIVE => 'AMQP_EXCLUSIVE',
+ \AMQP_AUTODELETE => 'AMQP_AUTODELETE',
+ \AMQP_INTERNAL => 'AMQP_INTERNAL',
+ \AMQP_NOLOCAL => 'AMQP_NOLOCAL',
+ \AMQP_AUTOACK => 'AMQP_AUTOACK',
+ \AMQP_IFEMPTY => 'AMQP_IFEMPTY',
+ \AMQP_IFUNUSED => 'AMQP_IFUNUSED',
+ \AMQP_MANDATORY => 'AMQP_MANDATORY',
+ \AMQP_IMMEDIATE => 'AMQP_IMMEDIATE',
+ \AMQP_MULTIPLE => 'AMQP_MULTIPLE',
+ \AMQP_NOWAIT => 'AMQP_NOWAIT',
+ \AMQP_REQUEUE => 'AMQP_REQUEUE',
+ ];
+
+ private const EXCHANGE_TYPES = [
+ \AMQP_EX_TYPE_DIRECT => 'AMQP_EX_TYPE_DIRECT',
+ \AMQP_EX_TYPE_FANOUT => 'AMQP_EX_TYPE_FANOUT',
+ \AMQP_EX_TYPE_TOPIC => 'AMQP_EX_TYPE_TOPIC',
+ \AMQP_EX_TYPE_HEADERS => 'AMQP_EX_TYPE_HEADERS',
+ ];
+
+ public static function castConnection(\AMQPConnection $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'is_connected' => $c->isConnected(),
+ ];
+
+ // Recent version of the extension already expose private properties
+ if (isset($a["\x00AMQPConnection\x00login"])) {
+ return $a;
+ }
+
+ // BC layer in the amqp lib
+ if (method_exists($c, 'getReadTimeout')) {
+ $timeout = $c->getReadTimeout();
+ } else {
+ $timeout = $c->getTimeout();
+ }
+
+ $a += [
+ $prefix.'is_connected' => $c->isConnected(),
+ $prefix.'login' => $c->getLogin(),
+ $prefix.'password' => $c->getPassword(),
+ $prefix.'host' => $c->getHost(),
+ $prefix.'vhost' => $c->getVhost(),
+ $prefix.'port' => $c->getPort(),
+ $prefix.'read_timeout' => $timeout,
+ ];
+
+ return $a;
+ }
+
+ public static function castChannel(\AMQPChannel $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'is_connected' => $c->isConnected(),
+ $prefix.'channel_id' => $c->getChannelId(),
+ ];
+
+ // Recent version of the extension already expose private properties
+ if (isset($a["\x00AMQPChannel\x00connection"])) {
+ return $a;
+ }
+
+ $a += [
+ $prefix.'connection' => $c->getConnection(),
+ $prefix.'prefetch_size' => $c->getPrefetchSize(),
+ $prefix.'prefetch_count' => $c->getPrefetchCount(),
+ ];
+
+ return $a;
+ }
+
+ public static function castQueue(\AMQPQueue $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'flags' => self::extractFlags($c->getFlags()),
+ ];
+
+ // Recent version of the extension already expose private properties
+ if (isset($a["\x00AMQPQueue\x00name"])) {
+ return $a;
+ }
+
+ $a += [
+ $prefix.'connection' => $c->getConnection(),
+ $prefix.'channel' => $c->getChannel(),
+ $prefix.'name' => $c->getName(),
+ $prefix.'arguments' => $c->getArguments(),
+ ];
+
+ return $a;
+ }
+
+ public static function castExchange(\AMQPExchange $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'flags' => self::extractFlags($c->getFlags()),
+ ];
+
+ $type = isset(self::EXCHANGE_TYPES[$c->getType()]) ? new ConstStub(self::EXCHANGE_TYPES[$c->getType()], $c->getType()) : $c->getType();
+
+ // Recent version of the extension already expose private properties
+ if (isset($a["\x00AMQPExchange\x00name"])) {
+ $a["\x00AMQPExchange\x00type"] = $type;
+
+ return $a;
+ }
+
+ $a += [
+ $prefix.'connection' => $c->getConnection(),
+ $prefix.'channel' => $c->getChannel(),
+ $prefix.'name' => $c->getName(),
+ $prefix.'type' => $type,
+ $prefix.'arguments' => $c->getArguments(),
+ ];
+
+ return $a;
+ }
+
+ public static function castEnvelope(\AMQPEnvelope $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $deliveryMode = new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode());
+
+ // Recent version of the extension already expose private properties
+ if (isset($a["\x00AMQPEnvelope\x00body"])) {
+ $a["\0AMQPEnvelope\0delivery_mode"] = $deliveryMode;
+
+ return $a;
+ }
+
+ if (!($filter & Caster::EXCLUDE_VERBOSE)) {
+ $a += [$prefix.'body' => $c->getBody()];
+ }
+
+ $a += [
+ $prefix.'delivery_tag' => $c->getDeliveryTag(),
+ $prefix.'is_redelivery' => $c->isRedelivery(),
+ $prefix.'exchange_name' => $c->getExchangeName(),
+ $prefix.'routing_key' => $c->getRoutingKey(),
+ $prefix.'content_type' => $c->getContentType(),
+ $prefix.'content_encoding' => $c->getContentEncoding(),
+ $prefix.'headers' => $c->getHeaders(),
+ $prefix.'delivery_mode' => $deliveryMode,
+ $prefix.'priority' => $c->getPriority(),
+ $prefix.'correlation_id' => $c->getCorrelationId(),
+ $prefix.'reply_to' => $c->getReplyTo(),
+ $prefix.'expiration' => $c->getExpiration(),
+ $prefix.'message_id' => $c->getMessageId(),
+ $prefix.'timestamp' => $c->getTimeStamp(),
+ $prefix.'type' => $c->getType(),
+ $prefix.'user_id' => $c->getUserId(),
+ $prefix.'app_id' => $c->getAppId(),
+ ];
+
+ return $a;
+ }
+
+ private static function extractFlags(int $flags): ConstStub
+ {
+ $flagsArray = [];
+
+ foreach (self::FLAGS as $value => $name) {
+ if ($flags & $value) {
+ $flagsArray[] = $name;
+ }
+ }
+
+ if (!$flagsArray) {
+ $flagsArray = ['AMQP_NOPARAM'];
+ }
+
+ return new ConstStub(implode('|', $flagsArray), $flags);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ArgsStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ArgsStub.php
new file mode 100644
index 0000000..f8b485b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ArgsStub.php
@@ -0,0 +1,80 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Represents a list of function arguments.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ArgsStub extends EnumStub
+{
+ private static $parameters = [];
+
+ public function __construct(array $args, string $function, ?string $class)
+ {
+ [$variadic, $params] = self::getParameters($function, $class);
+
+ $values = [];
+ foreach ($args as $k => $v) {
+ $values[$k] = !is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v;
+ }
+ if (null === $params) {
+ parent::__construct($values, false);
+
+ return;
+ }
+ if (\count($values) < \count($params)) {
+ $params = \array_slice($params, 0, \count($values));
+ } elseif (\count($values) > \count($params)) {
+ $values[] = new EnumStub(array_splice($values, \count($params)), false);
+ $params[] = $variadic;
+ }
+ if (['...'] === $params) {
+ $this->dumpKeys = false;
+ $this->value = $values[0]->value;
+ } else {
+ $this->value = array_combine($params, $values);
+ }
+ }
+
+ private static function getParameters(string $function, ?string $class): array
+ {
+ if (isset(self::$parameters[$k = $class.'::'.$function])) {
+ return self::$parameters[$k];
+ }
+
+ try {
+ $r = null !== $class ? new \ReflectionMethod($class, $function) : new \ReflectionFunction($function);
+ } catch (\ReflectionException $e) {
+ return [null, null];
+ }
+
+ $variadic = '...';
+ $params = [];
+ foreach ($r->getParameters() as $v) {
+ $k = '$'.$v->name;
+ if ($v->isPassedByReference()) {
+ $k = '&'.$k;
+ }
+ if ($v->isVariadic()) {
+ $variadic .= $k;
+ } else {
+ $params[] = $k;
+ }
+ }
+
+ return self::$parameters[$k] = [$variadic, $params];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/Caster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/Caster.php
new file mode 100644
index 0000000..612b21f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/Caster.php
@@ -0,0 +1,174 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Helper for filtering out properties in casters.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class Caster
+{
+ public const EXCLUDE_VERBOSE = 1;
+ public const EXCLUDE_VIRTUAL = 2;
+ public const EXCLUDE_DYNAMIC = 4;
+ public const EXCLUDE_PUBLIC = 8;
+ public const EXCLUDE_PROTECTED = 16;
+ public const EXCLUDE_PRIVATE = 32;
+ public const EXCLUDE_NULL = 64;
+ public const EXCLUDE_EMPTY = 128;
+ public const EXCLUDE_NOT_IMPORTANT = 256;
+ public const EXCLUDE_STRICT = 512;
+
+ public const PREFIX_VIRTUAL = "\0~\0";
+ public const PREFIX_DYNAMIC = "\0+\0";
+ public const PREFIX_PROTECTED = "\0*\0";
+
+ /**
+ * Casts objects to arrays and adds the dynamic property prefix.
+ *
+ * @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not
+ *
+ * @return array The array-cast of the object, with prefixed dynamic properties
+ */
+ public static function castObject(object $obj, string $class, bool $hasDebugInfo = false, string $debugClass = null): array
+ {
+ if ($hasDebugInfo) {
+ try {
+ $debugInfo = $obj->__debugInfo();
+ } catch (\Exception $e) {
+ // ignore failing __debugInfo()
+ $hasDebugInfo = false;
+ }
+ }
+
+ $a = $obj instanceof \Closure ? [] : (array) $obj;
+
+ if ($obj instanceof \__PHP_Incomplete_Class) {
+ return $a;
+ }
+
+ if ($a) {
+ static $publicProperties = [];
+ $debugClass = $debugClass ?? get_debug_type($obj);
+
+ $i = 0;
+ $prefixedKeys = [];
+ foreach ($a as $k => $v) {
+ if ("\0" !== ($k[0] ?? '')) {
+ if (!isset($publicProperties[$class])) {
+ foreach ((new \ReflectionClass($class))->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
+ $publicProperties[$class][$prop->name] = true;
+ }
+ }
+ if (!isset($publicProperties[$class][$k])) {
+ $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k;
+ }
+ } elseif ($debugClass !== $class && 1 === strpos($k, $class)) {
+ $prefixedKeys[$i] = "\0".$debugClass.strrchr($k, "\0");
+ }
+ ++$i;
+ }
+ if ($prefixedKeys) {
+ $keys = array_keys($a);
+ foreach ($prefixedKeys as $i => $k) {
+ $keys[$i] = $k;
+ }
+ $a = array_combine($keys, $a);
+ }
+ }
+
+ if ($hasDebugInfo && \is_array($debugInfo)) {
+ foreach ($debugInfo as $k => $v) {
+ if (!isset($k[0]) || "\0" !== $k[0]) {
+ if (\array_key_exists(self::PREFIX_DYNAMIC.$k, $a)) {
+ continue;
+ }
+ $k = self::PREFIX_VIRTUAL.$k;
+ }
+
+ unset($a[$k]);
+ $a[$k] = $v;
+ }
+ }
+
+ return $a;
+ }
+
+ /**
+ * Filters out the specified properties.
+ *
+ * By default, a single match in the $filter bit field filters properties out, following an "or" logic.
+ * When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed.
+ *
+ * @param array $a The array containing the properties to filter
+ * @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out
+ * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set
+ * @param int &$count Set to the number of removed properties
+ *
+ * @return array The filtered array
+ */
+ public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array
+ {
+ $count = 0;
+
+ foreach ($a as $k => $v) {
+ $type = self::EXCLUDE_STRICT & $filter;
+
+ if (null === $v) {
+ $type |= self::EXCLUDE_NULL & $filter;
+ $type |= self::EXCLUDE_EMPTY & $filter;
+ } elseif (false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) {
+ $type |= self::EXCLUDE_EMPTY & $filter;
+ }
+ if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !\in_array($k, $listedProperties, true)) {
+ $type |= self::EXCLUDE_NOT_IMPORTANT;
+ }
+ if ((self::EXCLUDE_VERBOSE & $filter) && \in_array($k, $listedProperties, true)) {
+ $type |= self::EXCLUDE_VERBOSE;
+ }
+
+ if (!isset($k[1]) || "\0" !== $k[0]) {
+ $type |= self::EXCLUDE_PUBLIC & $filter;
+ } elseif ('~' === $k[1]) {
+ $type |= self::EXCLUDE_VIRTUAL & $filter;
+ } elseif ('+' === $k[1]) {
+ $type |= self::EXCLUDE_DYNAMIC & $filter;
+ } elseif ('*' === $k[1]) {
+ $type |= self::EXCLUDE_PROTECTED & $filter;
+ } else {
+ $type |= self::EXCLUDE_PRIVATE & $filter;
+ }
+
+ if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) {
+ unset($a[$k]);
+ ++$count;
+ }
+ }
+
+ return $a;
+ }
+
+ public static function castPhpIncompleteClass(\__PHP_Incomplete_Class $c, array $a, Stub $stub, bool $isNested): array
+ {
+ if (isset($a['__PHP_Incomplete_Class_Name'])) {
+ $stub->class .= '('.$a['__PHP_Incomplete_Class_Name'].')';
+ unset($a['__PHP_Incomplete_Class_Name']);
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ClassStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ClassStub.php
new file mode 100644
index 0000000..48f8483
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ClassStub.php
@@ -0,0 +1,106 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Represents a PHP class identifier.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ClassStub extends ConstStub
+{
+ /**
+ * @param string $identifier A PHP identifier, e.g. a class, method, interface, etc. name
+ * @param callable $callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier
+ */
+ public function __construct(string $identifier, $callable = null)
+ {
+ $this->value = $identifier;
+
+ try {
+ if (null !== $callable) {
+ if ($callable instanceof \Closure) {
+ $r = new \ReflectionFunction($callable);
+ } elseif (\is_object($callable)) {
+ $r = [$callable, '__invoke'];
+ } elseif (\is_array($callable)) {
+ $r = $callable;
+ } elseif (false !== $i = strpos($callable, '::')) {
+ $r = [substr($callable, 0, $i), substr($callable, 2 + $i)];
+ } else {
+ $r = new \ReflectionFunction($callable);
+ }
+ } elseif (0 < $i = strpos($identifier, '::') ?: strpos($identifier, '->')) {
+ $r = [substr($identifier, 0, $i), substr($identifier, 2 + $i)];
+ } else {
+ $r = new \ReflectionClass($identifier);
+ }
+
+ if (\is_array($r)) {
+ try {
+ $r = new \ReflectionMethod($r[0], $r[1]);
+ } catch (\ReflectionException $e) {
+ $r = new \ReflectionClass($r[0]);
+ }
+ }
+
+ if (str_contains($identifier, "@anonymous\0")) {
+ $this->value = $identifier = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
+ return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];
+ }, $identifier);
+ }
+
+ if (null !== $callable && $r instanceof \ReflectionFunctionAbstract) {
+ $s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), true, Caster::EXCLUDE_VERBOSE);
+ $s = ReflectionCaster::getSignature($s);
+
+ if (str_ends_with($identifier, '()')) {
+ $this->value = substr_replace($identifier, $s, -2);
+ } else {
+ $this->value .= $s;
+ }
+ }
+ } catch (\ReflectionException $e) {
+ return;
+ } finally {
+ if (0 < $i = strrpos($this->value, '\\')) {
+ $this->attr['ellipsis'] = \strlen($this->value) - $i;
+ $this->attr['ellipsis-type'] = 'class';
+ $this->attr['ellipsis-tail'] = 1;
+ }
+ }
+
+ if ($f = $r->getFileName()) {
+ $this->attr['file'] = $f;
+ $this->attr['line'] = $r->getStartLine();
+ }
+ }
+
+ public static function wrapCallable($callable)
+ {
+ if (\is_object($callable) || !\is_callable($callable)) {
+ return $callable;
+ }
+
+ if (!\is_array($callable)) {
+ $callable = new static($callable, $callable);
+ } elseif (\is_string($callable[0])) {
+ $callable[0] = new static($callable[0], $callable);
+ } else {
+ $callable[1] = new static($callable[1], $callable);
+ }
+
+ return $callable;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ConstStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ConstStub.php
new file mode 100644
index 0000000..8b01797
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ConstStub.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Represents a PHP constant and its value.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ConstStub extends Stub
+{
+ public function __construct(string $name, $value = null)
+ {
+ $this->class = $name;
+ $this->value = 1 < \func_num_args() ? $value : $name;
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ return (string) $this->value;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/CutArrayStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/CutArrayStub.php
new file mode 100644
index 0000000..0e4fb36
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/CutArrayStub.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+/**
+ * Represents a cut array.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class CutArrayStub extends CutStub
+{
+ public $preservedSubset;
+
+ public function __construct(array $value, array $preservedKeys)
+ {
+ parent::__construct($value);
+
+ $this->preservedSubset = array_intersect_key($value, array_flip($preservedKeys));
+ $this->cut -= \count($this->preservedSubset);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/CutStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/CutStub.php
new file mode 100644
index 0000000..464c6db
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/CutStub.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Represents the main properties of a PHP variable, pre-casted by a caster.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class CutStub extends Stub
+{
+ public function __construct($value)
+ {
+ $this->value = $value;
+
+ switch (\gettype($value)) {
+ case 'object':
+ $this->type = self::TYPE_OBJECT;
+ $this->class = \get_class($value);
+
+ if ($value instanceof \Closure) {
+ ReflectionCaster::castClosure($value, [], $this, true, Caster::EXCLUDE_VERBOSE);
+ }
+
+ $this->cut = -1;
+ break;
+
+ case 'array':
+ $this->type = self::TYPE_ARRAY;
+ $this->class = self::ARRAY_ASSOC;
+ $this->cut = $this->value = \count($value);
+ break;
+
+ case 'resource':
+ case 'unknown type':
+ case 'resource (closed)':
+ $this->type = self::TYPE_RESOURCE;
+ $this->handle = (int) $value;
+ if ('Unknown' === $this->class = @get_resource_type($value)) {
+ $this->class = 'Closed';
+ }
+ $this->cut = -1;
+ break;
+
+ case 'string':
+ $this->type = self::TYPE_STRING;
+ $this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY;
+ $this->cut = self::STRING_BINARY === $this->class ? \strlen($value) : mb_strlen($value, 'UTF-8');
+ $this->value = '';
+ break;
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DOMCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DOMCaster.php
new file mode 100644
index 0000000..4dd16e0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DOMCaster.php
@@ -0,0 +1,304 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts DOM related classes to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class DOMCaster
+{
+ private const ERROR_CODES = [
+ \DOM_PHP_ERR => 'DOM_PHP_ERR',
+ \DOM_INDEX_SIZE_ERR => 'DOM_INDEX_SIZE_ERR',
+ \DOMSTRING_SIZE_ERR => 'DOMSTRING_SIZE_ERR',
+ \DOM_HIERARCHY_REQUEST_ERR => 'DOM_HIERARCHY_REQUEST_ERR',
+ \DOM_WRONG_DOCUMENT_ERR => 'DOM_WRONG_DOCUMENT_ERR',
+ \DOM_INVALID_CHARACTER_ERR => 'DOM_INVALID_CHARACTER_ERR',
+ \DOM_NO_DATA_ALLOWED_ERR => 'DOM_NO_DATA_ALLOWED_ERR',
+ \DOM_NO_MODIFICATION_ALLOWED_ERR => 'DOM_NO_MODIFICATION_ALLOWED_ERR',
+ \DOM_NOT_FOUND_ERR => 'DOM_NOT_FOUND_ERR',
+ \DOM_NOT_SUPPORTED_ERR => 'DOM_NOT_SUPPORTED_ERR',
+ \DOM_INUSE_ATTRIBUTE_ERR => 'DOM_INUSE_ATTRIBUTE_ERR',
+ \DOM_INVALID_STATE_ERR => 'DOM_INVALID_STATE_ERR',
+ \DOM_SYNTAX_ERR => 'DOM_SYNTAX_ERR',
+ \DOM_INVALID_MODIFICATION_ERR => 'DOM_INVALID_MODIFICATION_ERR',
+ \DOM_NAMESPACE_ERR => 'DOM_NAMESPACE_ERR',
+ \DOM_INVALID_ACCESS_ERR => 'DOM_INVALID_ACCESS_ERR',
+ \DOM_VALIDATION_ERR => 'DOM_VALIDATION_ERR',
+ ];
+
+ private const NODE_TYPES = [
+ \XML_ELEMENT_NODE => 'XML_ELEMENT_NODE',
+ \XML_ATTRIBUTE_NODE => 'XML_ATTRIBUTE_NODE',
+ \XML_TEXT_NODE => 'XML_TEXT_NODE',
+ \XML_CDATA_SECTION_NODE => 'XML_CDATA_SECTION_NODE',
+ \XML_ENTITY_REF_NODE => 'XML_ENTITY_REF_NODE',
+ \XML_ENTITY_NODE => 'XML_ENTITY_NODE',
+ \XML_PI_NODE => 'XML_PI_NODE',
+ \XML_COMMENT_NODE => 'XML_COMMENT_NODE',
+ \XML_DOCUMENT_NODE => 'XML_DOCUMENT_NODE',
+ \XML_DOCUMENT_TYPE_NODE => 'XML_DOCUMENT_TYPE_NODE',
+ \XML_DOCUMENT_FRAG_NODE => 'XML_DOCUMENT_FRAG_NODE',
+ \XML_NOTATION_NODE => 'XML_NOTATION_NODE',
+ \XML_HTML_DOCUMENT_NODE => 'XML_HTML_DOCUMENT_NODE',
+ \XML_DTD_NODE => 'XML_DTD_NODE',
+ \XML_ELEMENT_DECL_NODE => 'XML_ELEMENT_DECL_NODE',
+ \XML_ATTRIBUTE_DECL_NODE => 'XML_ATTRIBUTE_DECL_NODE',
+ \XML_ENTITY_DECL_NODE => 'XML_ENTITY_DECL_NODE',
+ \XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE',
+ ];
+
+ public static function castException(\DOMException $e, array $a, Stub $stub, bool $isNested)
+ {
+ $k = Caster::PREFIX_PROTECTED.'code';
+ if (isset($a[$k], self::ERROR_CODES[$a[$k]])) {
+ $a[$k] = new ConstStub(self::ERROR_CODES[$a[$k]], $a[$k]);
+ }
+
+ return $a;
+ }
+
+ public static function castLength($dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'length' => $dom->length,
+ ];
+
+ return $a;
+ }
+
+ public static function castImplementation(\DOMImplementation $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'Core' => '1.0',
+ Caster::PREFIX_VIRTUAL.'XML' => '2.0',
+ ];
+
+ return $a;
+ }
+
+ public static function castNode(\DOMNode $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'nodeName' => $dom->nodeName,
+ 'nodeValue' => new CutStub($dom->nodeValue),
+ 'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType),
+ 'parentNode' => new CutStub($dom->parentNode),
+ 'childNodes' => $dom->childNodes,
+ 'firstChild' => new CutStub($dom->firstChild),
+ 'lastChild' => new CutStub($dom->lastChild),
+ 'previousSibling' => new CutStub($dom->previousSibling),
+ 'nextSibling' => new CutStub($dom->nextSibling),
+ 'attributes' => $dom->attributes,
+ 'ownerDocument' => new CutStub($dom->ownerDocument),
+ 'namespaceURI' => $dom->namespaceURI,
+ 'prefix' => $dom->prefix,
+ 'localName' => $dom->localName,
+ 'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI,
+ 'textContent' => new CutStub($dom->textContent),
+ ];
+
+ return $a;
+ }
+
+ public static function castNameSpaceNode(\DOMNameSpaceNode $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'nodeName' => $dom->nodeName,
+ 'nodeValue' => new CutStub($dom->nodeValue),
+ 'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType),
+ 'prefix' => $dom->prefix,
+ 'localName' => $dom->localName,
+ 'namespaceURI' => $dom->namespaceURI,
+ 'ownerDocument' => new CutStub($dom->ownerDocument),
+ 'parentNode' => new CutStub($dom->parentNode),
+ ];
+
+ return $a;
+ }
+
+ public static function castDocument(\DOMDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0)
+ {
+ $a += [
+ 'doctype' => $dom->doctype,
+ 'implementation' => $dom->implementation,
+ 'documentElement' => new CutStub($dom->documentElement),
+ 'actualEncoding' => $dom->actualEncoding,
+ 'encoding' => $dom->encoding,
+ 'xmlEncoding' => $dom->xmlEncoding,
+ 'standalone' => $dom->standalone,
+ 'xmlStandalone' => $dom->xmlStandalone,
+ 'version' => $dom->version,
+ 'xmlVersion' => $dom->xmlVersion,
+ 'strictErrorChecking' => $dom->strictErrorChecking,
+ 'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI,
+ 'config' => $dom->config,
+ 'formatOutput' => $dom->formatOutput,
+ 'validateOnParse' => $dom->validateOnParse,
+ 'resolveExternals' => $dom->resolveExternals,
+ 'preserveWhiteSpace' => $dom->preserveWhiteSpace,
+ 'recover' => $dom->recover,
+ 'substituteEntities' => $dom->substituteEntities,
+ ];
+
+ if (!($filter & Caster::EXCLUDE_VERBOSE)) {
+ $formatOutput = $dom->formatOutput;
+ $dom->formatOutput = true;
+ $a += [Caster::PREFIX_VIRTUAL.'xml' => $dom->saveXML()];
+ $dom->formatOutput = $formatOutput;
+ }
+
+ return $a;
+ }
+
+ public static function castCharacterData(\DOMCharacterData $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'data' => $dom->data,
+ 'length' => $dom->length,
+ ];
+
+ return $a;
+ }
+
+ public static function castAttr(\DOMAttr $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'name' => $dom->name,
+ 'specified' => $dom->specified,
+ 'value' => $dom->value,
+ 'ownerElement' => $dom->ownerElement,
+ 'schemaTypeInfo' => $dom->schemaTypeInfo,
+ ];
+
+ return $a;
+ }
+
+ public static function castElement(\DOMElement $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'tagName' => $dom->tagName,
+ 'schemaTypeInfo' => $dom->schemaTypeInfo,
+ ];
+
+ return $a;
+ }
+
+ public static function castText(\DOMText $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'wholeText' => $dom->wholeText,
+ ];
+
+ return $a;
+ }
+
+ public static function castTypeinfo(\DOMTypeinfo $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'typeName' => $dom->typeName,
+ 'typeNamespace' => $dom->typeNamespace,
+ ];
+
+ return $a;
+ }
+
+ public static function castDomError(\DOMDomError $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'severity' => $dom->severity,
+ 'message' => $dom->message,
+ 'type' => $dom->type,
+ 'relatedException' => $dom->relatedException,
+ 'related_data' => $dom->related_data,
+ 'location' => $dom->location,
+ ];
+
+ return $a;
+ }
+
+ public static function castLocator(\DOMLocator $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'lineNumber' => $dom->lineNumber,
+ 'columnNumber' => $dom->columnNumber,
+ 'offset' => $dom->offset,
+ 'relatedNode' => $dom->relatedNode,
+ 'uri' => $dom->uri ? new LinkStub($dom->uri, $dom->lineNumber) : $dom->uri,
+ ];
+
+ return $a;
+ }
+
+ public static function castDocumentType(\DOMDocumentType $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'name' => $dom->name,
+ 'entities' => $dom->entities,
+ 'notations' => $dom->notations,
+ 'publicId' => $dom->publicId,
+ 'systemId' => $dom->systemId,
+ 'internalSubset' => $dom->internalSubset,
+ ];
+
+ return $a;
+ }
+
+ public static function castNotation(\DOMNotation $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'publicId' => $dom->publicId,
+ 'systemId' => $dom->systemId,
+ ];
+
+ return $a;
+ }
+
+ public static function castEntity(\DOMEntity $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'publicId' => $dom->publicId,
+ 'systemId' => $dom->systemId,
+ 'notationName' => $dom->notationName,
+ 'actualEncoding' => $dom->actualEncoding,
+ 'encoding' => $dom->encoding,
+ 'version' => $dom->version,
+ ];
+
+ return $a;
+ }
+
+ public static function castProcessingInstruction(\DOMProcessingInstruction $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'target' => $dom->target,
+ 'data' => $dom->data,
+ ];
+
+ return $a;
+ }
+
+ public static function castXPath(\DOMXPath $dom, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ 'document' => $dom->document,
+ ];
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DateCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DateCaster.php
new file mode 100644
index 0000000..1f61c32
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DateCaster.php
@@ -0,0 +1,126 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts DateTimeInterface related classes to array representation.
+ *
+ * @author Dany Maillard <danymaillard93b@gmail.com>
+ *
+ * @final
+ */
+class DateCaster
+{
+ private const PERIOD_LIMIT = 3;
+
+ public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, bool $isNested, int $filter)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+ $location = $d->getTimezone()->getLocation();
+ $fromNow = (new \DateTime())->diff($d);
+
+ $title = $d->format('l, F j, Y')
+ ."\n".self::formatInterval($fromNow).' from now'
+ .($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '')
+ ;
+
+ unset(
+ $a[Caster::PREFIX_DYNAMIC.'date'],
+ $a[Caster::PREFIX_DYNAMIC.'timezone'],
+ $a[Caster::PREFIX_DYNAMIC.'timezone_type']
+ );
+ $a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title);
+
+ $stub->class .= $d->format(' @U');
+
+ return $a;
+ }
+
+ public static function castInterval(\DateInterval $interval, array $a, Stub $stub, bool $isNested, int $filter)
+ {
+ $now = new \DateTimeImmutable();
+ $numberOfSeconds = $now->add($interval)->getTimestamp() - $now->getTimestamp();
+ $title = number_format($numberOfSeconds, 0, '.', ' ').'s';
+
+ $i = [Caster::PREFIX_VIRTUAL.'interval' => new ConstStub(self::formatInterval($interval), $title)];
+
+ return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a;
+ }
+
+ private static function formatInterval(\DateInterval $i): string
+ {
+ $format = '%R ';
+
+ if (0 === $i->y && 0 === $i->m && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) {
+ $i = date_diff($d = new \DateTime(), date_add(clone $d, $i)); // recalculate carry over points
+ $format .= 0 < $i->days ? '%ad ' : '';
+ } else {
+ $format .= ($i->y ? '%yy ' : '').($i->m ? '%mm ' : '').($i->d ? '%dd ' : '');
+ }
+
+ $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, substr($i->f, 2)) : '';
+ $format = '%R ' === $format ? '0s' : $format;
+
+ return $i->format(rtrim($format));
+ }
+
+ public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stub, bool $isNested, int $filter)
+ {
+ $location = $timeZone->getLocation();
+ $formatted = (new \DateTime('now', $timeZone))->format($location ? 'e (P)' : 'P');
+ $title = $location && \extension_loaded('intl') ? \Locale::getDisplayRegion('-'.$location['country_code']) : '';
+
+ $z = [Caster::PREFIX_VIRTUAL.'timezone' => new ConstStub($formatted, $title)];
+
+ return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a;
+ }
+
+ public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, bool $isNested, int $filter)
+ {
+ $dates = [];
+ foreach (clone $p as $i => $d) {
+ if (self::PERIOD_LIMIT === $i) {
+ $now = new \DateTimeImmutable('now', new \DateTimeZone('UTC'));
+ $dates[] = sprintf('%s more', ($end = $p->getEndDate())
+ ? ceil(($end->format('U.u') - $d->format('U.u')) / ((int) $now->add($p->getDateInterval())->format('U.u') - (int) $now->format('U.u')))
+ : $p->recurrences - $i
+ );
+ break;
+ }
+ $dates[] = sprintf('%s) %s', $i + 1, self::formatDateTime($d));
+ }
+
+ $period = sprintf(
+ 'every %s, from %s (%s) %s',
+ self::formatInterval($p->getDateInterval()),
+ self::formatDateTime($p->getStartDate()),
+ $p->include_start_date ? 'included' : 'excluded',
+ ($end = $p->getEndDate()) ? 'to '.self::formatDateTime($end) : 'recurring '.$p->recurrences.' time/s'
+ );
+
+ $p = [Caster::PREFIX_VIRTUAL.'period' => new ConstStub($period, implode("\n", $dates))];
+
+ return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a;
+ }
+
+ private static function formatDateTime(\DateTimeInterface $d, string $extra = ''): string
+ {
+ return $d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).$extra);
+ }
+
+ private static function formatSeconds(string $s, string $us): string
+ {
+ return sprintf('%02d.%s', $s, 0 === ($len = \strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us));
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DoctrineCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DoctrineCaster.php
new file mode 100644
index 0000000..129b2cb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DoctrineCaster.php
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Doctrine\Common\Proxy\Proxy as CommonProxy;
+use Doctrine\ORM\PersistentCollection;
+use Doctrine\ORM\Proxy\Proxy as OrmProxy;
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts Doctrine related classes to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class DoctrineCaster
+{
+ public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, bool $isNested)
+ {
+ foreach (['__cloner__', '__initializer__'] as $k) {
+ if (\array_key_exists($k, $a)) {
+ unset($a[$k]);
+ ++$stub->cut;
+ }
+ }
+
+ return $a;
+ }
+
+ public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, bool $isNested)
+ {
+ foreach (['_entityPersister', '_identifier'] as $k) {
+ if (\array_key_exists($k = "\0Doctrine\\ORM\\Proxy\\Proxy\0".$k, $a)) {
+ unset($a[$k]);
+ ++$stub->cut;
+ }
+ }
+
+ return $a;
+ }
+
+ public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, bool $isNested)
+ {
+ foreach (['snapshot', 'association', 'typeClass'] as $k) {
+ if (\array_key_exists($k = "\0Doctrine\\ORM\\PersistentCollection\0".$k, $a)) {
+ $a[$k] = new CutStub($a[$k]);
+ }
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DsCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DsCaster.php
new file mode 100644
index 0000000..b34b670
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DsCaster.php
@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Ds\Collection;
+use Ds\Map;
+use Ds\Pair;
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts Ds extension classes to array representation.
+ *
+ * @author Jáchym Toušek <enumag@gmail.com>
+ *
+ * @final
+ */
+class DsCaster
+{
+ public static function castCollection(Collection $c, array $a, Stub $stub, bool $isNested): array
+ {
+ $a[Caster::PREFIX_VIRTUAL.'count'] = $c->count();
+ $a[Caster::PREFIX_VIRTUAL.'capacity'] = $c->capacity();
+
+ if (!$c instanceof Map) {
+ $a += $c->toArray();
+ }
+
+ return $a;
+ }
+
+ public static function castMap(Map $c, array $a, Stub $stub, bool $isNested): array
+ {
+ foreach ($c as $k => $v) {
+ $a[] = new DsPairStub($k, $v);
+ }
+
+ return $a;
+ }
+
+ public static function castPair(Pair $c, array $a, Stub $stub, bool $isNested): array
+ {
+ foreach ($c->toArray() as $k => $v) {
+ $a[Caster::PREFIX_VIRTUAL.$k] = $v;
+ }
+
+ return $a;
+ }
+
+ public static function castPairStub(DsPairStub $c, array $a, Stub $stub, bool $isNested): array
+ {
+ if ($isNested) {
+ $stub->class = Pair::class;
+ $stub->value = null;
+ $stub->handle = 0;
+
+ $a = $c->value;
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DsPairStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DsPairStub.php
new file mode 100644
index 0000000..a1dcc15
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DsPairStub.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class DsPairStub extends Stub
+{
+ public function __construct($key, $value)
+ {
+ $this->value = [
+ Caster::PREFIX_VIRTUAL.'key' => $key,
+ Caster::PREFIX_VIRTUAL.'value' => $value,
+ ];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/EnumStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/EnumStub.php
new file mode 100644
index 0000000..7a4e98a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/EnumStub.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Represents an enumeration of values.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class EnumStub extends Stub
+{
+ public $dumpKeys = true;
+
+ public function __construct(array $values, bool $dumpKeys = true)
+ {
+ $this->value = $values;
+ $this->dumpKeys = $dumpKeys;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ExceptionCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ExceptionCaster.php
new file mode 100644
index 0000000..baa7a18
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ExceptionCaster.php
@@ -0,0 +1,382 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
+use Symfony\Component\VarDumper\Cloner\Stub;
+use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
+
+/**
+ * Casts common Exception classes to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class ExceptionCaster
+{
+ public static $srcContext = 1;
+ public static $traceArgs = true;
+ public static $errorTypes = [
+ \E_DEPRECATED => 'E_DEPRECATED',
+ \E_USER_DEPRECATED => 'E_USER_DEPRECATED',
+ \E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
+ \E_ERROR => 'E_ERROR',
+ \E_WARNING => 'E_WARNING',
+ \E_PARSE => 'E_PARSE',
+ \E_NOTICE => 'E_NOTICE',
+ \E_CORE_ERROR => 'E_CORE_ERROR',
+ \E_CORE_WARNING => 'E_CORE_WARNING',
+ \E_COMPILE_ERROR => 'E_COMPILE_ERROR',
+ \E_COMPILE_WARNING => 'E_COMPILE_WARNING',
+ \E_USER_ERROR => 'E_USER_ERROR',
+ \E_USER_WARNING => 'E_USER_WARNING',
+ \E_USER_NOTICE => 'E_USER_NOTICE',
+ \E_STRICT => 'E_STRICT',
+ ];
+
+ private static $framesCache = [];
+
+ public static function castError(\Error $e, array $a, Stub $stub, bool $isNested, int $filter = 0)
+ {
+ return self::filterExceptionArray($stub->class, $a, "\0Error\0", $filter);
+ }
+
+ public static function castException(\Exception $e, array $a, Stub $stub, bool $isNested, int $filter = 0)
+ {
+ return self::filterExceptionArray($stub->class, $a, "\0Exception\0", $filter);
+ }
+
+ public static function castErrorException(\ErrorException $e, array $a, Stub $stub, bool $isNested)
+ {
+ if (isset($a[$s = Caster::PREFIX_PROTECTED.'severity'], self::$errorTypes[$a[$s]])) {
+ $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]);
+ }
+
+ return $a;
+ }
+
+ public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, bool $isNested)
+ {
+ $trace = Caster::PREFIX_VIRTUAL.'trace';
+ $prefix = Caster::PREFIX_PROTECTED;
+ $xPrefix = "\0Exception\0";
+
+ if (isset($a[$xPrefix.'previous'], $a[$trace]) && $a[$xPrefix.'previous'] instanceof \Exception) {
+ $b = (array) $a[$xPrefix.'previous'];
+ $class = get_debug_type($a[$xPrefix.'previous']);
+ self::traceUnshift($b[$xPrefix.'trace'], $class, $b[$prefix.'file'], $b[$prefix.'line']);
+ $a[$trace] = new TraceStub($b[$xPrefix.'trace'], false, 0, -\count($a[$trace]->value));
+ }
+
+ unset($a[$xPrefix.'previous'], $a[$prefix.'code'], $a[$prefix.'file'], $a[$prefix.'line']);
+
+ return $a;
+ }
+
+ public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, bool $isNested)
+ {
+ $sPrefix = "\0".SilencedErrorContext::class."\0";
+
+ if (!isset($a[$s = $sPrefix.'severity'])) {
+ return $a;
+ }
+
+ if (isset(self::$errorTypes[$a[$s]])) {
+ $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]);
+ }
+
+ $trace = [[
+ 'file' => $a[$sPrefix.'file'],
+ 'line' => $a[$sPrefix.'line'],
+ ]];
+
+ if (isset($a[$sPrefix.'trace'])) {
+ $trace = array_merge($trace, $a[$sPrefix.'trace']);
+ }
+
+ unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']);
+ $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs);
+
+ return $a;
+ }
+
+ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, bool $isNested)
+ {
+ if (!$isNested) {
+ return $a;
+ }
+ $stub->class = '';
+ $stub->handle = 0;
+ $frames = $trace->value;
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a = [];
+ $j = \count($frames);
+ if (0 > $i = $trace->sliceOffset) {
+ $i = max(0, $j + $i);
+ }
+ if (!isset($trace->value[$i])) {
+ return [];
+ }
+ $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : '';
+ $frames[] = ['function' => ''];
+ $collapse = false;
+
+ for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) {
+ $f = $frames[$i];
+ $call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'] : '???';
+
+ $frame = new FrameStub(
+ [
+ 'object' => $f['object'] ?? null,
+ 'class' => $f['class'] ?? null,
+ 'type' => $f['type'] ?? null,
+ 'function' => $f['function'] ?? null,
+ ] + $frames[$i - 1],
+ false,
+ true
+ );
+ $f = self::castFrameStub($frame, [], $frame, true);
+ if (isset($f[$prefix.'src'])) {
+ foreach ($f[$prefix.'src']->value as $label => $frame) {
+ if (str_starts_with($label, "\0~collapse=0")) {
+ if ($collapse) {
+ $label = substr_replace($label, '1', 11, 1);
+ } else {
+ $collapse = true;
+ }
+ }
+ $label = substr_replace($label, "title=Stack level $j.&", 2, 0);
+ }
+ $f = $frames[$i - 1];
+ if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) {
+ $frame->value['arguments'] = new ArgsStub($f['args'], $f['function'] ?? null, $f['class'] ?? null);
+ }
+ } elseif ('???' !== $lastCall) {
+ $label = new ClassStub($lastCall);
+ if (isset($label->attr['ellipsis'])) {
+ $label->attr['ellipsis'] += 2;
+ $label = substr_replace($prefix, "ellipsis-type=class&ellipsis={$label->attr['ellipsis']}&ellipsis-tail=1&title=Stack level $j.", 2, 0).$label->value.'()';
+ } else {
+ $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$label->value.'()';
+ }
+ } else {
+ $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall;
+ }
+ $a[substr_replace($label, sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame;
+
+ $lastCall = $call;
+ }
+ if (null !== $trace->sliceLength) {
+ $a = \array_slice($a, 0, $trace->sliceLength, true);
+ }
+
+ return $a;
+ }
+
+ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, bool $isNested)
+ {
+ if (!$isNested) {
+ return $a;
+ }
+ $f = $frame->value;
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ if (isset($f['file'], $f['line'])) {
+ $cacheKey = $f;
+ unset($cacheKey['object'], $cacheKey['args']);
+ $cacheKey[] = self::$srcContext;
+ $cacheKey = implode('-', $cacheKey);
+
+ if (isset(self::$framesCache[$cacheKey])) {
+ $a[$prefix.'src'] = self::$framesCache[$cacheKey];
+ } else {
+ if (preg_match('/\((\d+)\)(?:\([\da-f]{32}\))? : (?:eval\(\)\'d code|runtime-created function)$/', $f['file'], $match)) {
+ $f['file'] = substr($f['file'], 0, -\strlen($match[0]));
+ $f['line'] = (int) $match[1];
+ }
+ $src = $f['line'];
+ $srcKey = $f['file'];
+ $ellipsis = new LinkStub($srcKey, 0);
+ $srcAttr = 'collapse='.(int) $ellipsis->inVendor;
+ $ellipsisTail = $ellipsis->attr['ellipsis-tail'] ?? 0;
+ $ellipsis = $ellipsis->attr['ellipsis'] ?? 0;
+
+ if (is_file($f['file']) && 0 <= self::$srcContext) {
+ if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) {
+ $template = $f['object'] ?? unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class']));
+
+ $ellipsis = 0;
+ $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
+ $templateInfo = $template->getDebugInfo();
+ if (isset($templateInfo[$f['line']])) {
+ if (!method_exists($template, 'getSourceContext') || !is_file($templatePath = $template->getSourceContext()->getPath())) {
+ $templatePath = null;
+ }
+ if ($templateSrc) {
+ $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f);
+ $srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']];
+ }
+ }
+ }
+ if ($srcKey == $f['file']) {
+ $src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, 'php', $f['file'], $f);
+ $srcKey .= ':'.$f['line'];
+ if ($ellipsis) {
+ $ellipsis += 1 + \strlen($f['line']);
+ }
+ }
+ $srcAttr .= sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']);
+ } else {
+ $srcAttr .= '&separator=:';
+ }
+ $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : '';
+ self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub(["\0~$srcAttr\0$srcKey" => $src]);
+ }
+ }
+
+ unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']);
+ if ($frame->inTraceStub) {
+ unset($a[$prefix.'class'], $a[$prefix.'type'], $a[$prefix.'function']);
+ }
+ foreach ($a as $k => $v) {
+ if (!$v) {
+ unset($a[$k]);
+ }
+ }
+ if ($frame->keepArgs && !empty($f['args'])) {
+ $a[$prefix.'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']);
+ }
+
+ return $a;
+ }
+
+ private static function filterExceptionArray(string $xClass, array $a, string $xPrefix, int $filter): array
+ {
+ if (isset($a[$xPrefix.'trace'])) {
+ $trace = $a[$xPrefix.'trace'];
+ unset($a[$xPrefix.'trace']); // Ensures the trace is always last
+ } else {
+ $trace = [];
+ }
+
+ if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) {
+ if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) {
+ self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']);
+ }
+ $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs);
+ }
+ if (empty($a[$xPrefix.'previous'])) {
+ unset($a[$xPrefix.'previous']);
+ }
+ unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']);
+
+ if (isset($a[Caster::PREFIX_PROTECTED.'message']) && str_contains($a[Caster::PREFIX_PROTECTED.'message'], "@anonymous\0")) {
+ $a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
+ return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];
+ }, $a[Caster::PREFIX_PROTECTED.'message']);
+ }
+
+ if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) {
+ $a[Caster::PREFIX_PROTECTED.'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']);
+ }
+
+ return $a;
+ }
+
+ private static function traceUnshift(array &$trace, ?string $class, string $file, int $line): void
+ {
+ if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) {
+ return;
+ }
+ array_unshift($trace, [
+ 'function' => $class ? 'new '.$class : null,
+ 'file' => $file,
+ 'line' => $line,
+ ]);
+ }
+
+ private static function extractSource(string $srcLines, int $line, int $srcContext, string $lang, ?string $file, array $frame): EnumStub
+ {
+ $srcLines = explode("\n", $srcLines);
+ $src = [];
+
+ for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) {
+ $src[] = ($srcLines[$i] ?? '')."\n";
+ }
+
+ if ($frame['function'] ?? false) {
+ $stub = new CutStub(new \stdClass());
+ $stub->class = (isset($frame['class']) ? $frame['class'].$frame['type'] : '').$frame['function'];
+ $stub->type = Stub::TYPE_OBJECT;
+ $stub->attr['cut_hash'] = true;
+ $stub->attr['file'] = $frame['file'];
+ $stub->attr['line'] = $frame['line'];
+
+ try {
+ $caller = isset($frame['class']) ? new \ReflectionMethod($frame['class'], $frame['function']) : new \ReflectionFunction($frame['function']);
+ $stub->class .= ReflectionCaster::getSignature(ReflectionCaster::castFunctionAbstract($caller, [], $stub, true, Caster::EXCLUDE_VERBOSE));
+
+ if ($f = $caller->getFileName()) {
+ $stub->attr['file'] = $f;
+ $stub->attr['line'] = $caller->getStartLine();
+ }
+ } catch (\ReflectionException $e) {
+ // ignore fake class/function
+ }
+
+ $srcLines = ["\0~separator=\0" => $stub];
+ } else {
+ $stub = null;
+ $srcLines = [];
+ }
+
+ $ltrim = 0;
+ do {
+ $pad = null;
+ for ($i = $srcContext << 1; $i >= 0; --$i) {
+ if (isset($src[$i][$ltrim]) && "\r" !== ($c = $src[$i][$ltrim]) && "\n" !== $c) {
+ if (null === $pad) {
+ $pad = $c;
+ }
+ if ((' ' !== $c && "\t" !== $c) || $pad !== $c) {
+ break;
+ }
+ }
+ }
+ ++$ltrim;
+ } while (0 > $i && null !== $pad);
+
+ --$ltrim;
+
+ foreach ($src as $i => $c) {
+ if ($ltrim) {
+ $c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t");
+ }
+ $c = substr($c, 0, -1);
+ if ($i !== $srcContext) {
+ $c = new ConstStub('default', $c);
+ } else {
+ $c = new ConstStub($c, $stub ? 'in '.$stub->class : '');
+ if (null !== $file) {
+ $c->attr['file'] = $file;
+ $c->attr['line'] = $line;
+ }
+ }
+ $c->attr['lang'] = $lang;
+ $srcLines[sprintf("\0~separator=› &%d\0", $i + $line - $srcContext)] = $c;
+ }
+
+ return new EnumStub($srcLines);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/FrameStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/FrameStub.php
new file mode 100644
index 0000000..8786755
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/FrameStub.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+/**
+ * Represents a single backtrace frame as returned by debug_backtrace() or Exception->getTrace().
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class FrameStub extends EnumStub
+{
+ public $keepArgs;
+ public $inTraceStub;
+
+ public function __construct(array $frame, bool $keepArgs = true, bool $inTraceStub = false)
+ {
+ $this->value = $frame;
+ $this->keepArgs = $keepArgs;
+ $this->inTraceStub = $inTraceStub;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/GmpCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/GmpCaster.php
new file mode 100644
index 0000000..b018cc7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/GmpCaster.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts GMP objects to array representation.
+ *
+ * @author Hamza Amrouche <hamza.simperfit@gmail.com>
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class GmpCaster
+{
+ public static function castGmp(\GMP $gmp, array $a, Stub $stub, bool $isNested, int $filter): array
+ {
+ $a[Caster::PREFIX_VIRTUAL.'value'] = new ConstStub(gmp_strval($gmp), gmp_strval($gmp));
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ImagineCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ImagineCaster.php
new file mode 100644
index 0000000..d1289da
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ImagineCaster.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Imagine\Image\ImageInterface;
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ */
+final class ImagineCaster
+{
+ public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested): array
+ {
+ $imgData = $c->get('png');
+ if (\strlen($imgData) > 1 * 1000 * 1000) {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'image' => new ConstStub($c->getSize()),
+ ];
+ } else {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'image' => new ImgStub($imgData, 'image/png', $c->getSize()),
+ ];
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ImgStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ImgStub.php
new file mode 100644
index 0000000..a16681f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ImgStub.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+/**
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ */
+class ImgStub extends ConstStub
+{
+ public function __construct(string $data, string $contentType, string $size = '')
+ {
+ $this->value = '';
+ $this->attr['img-data'] = $data;
+ $this->attr['img-size'] = $size;
+ $this->attr['content-type'] = $contentType;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/IntlCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/IntlCaster.php
new file mode 100644
index 0000000..23b9d5d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/IntlCaster.php
@@ -0,0 +1,172 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>
+ *
+ * @final
+ */
+class IntlCaster
+{
+ public static function castMessageFormatter(\MessageFormatter $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(),
+ Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(),
+ ];
+
+ return self::castError($c, $a);
+ }
+
+ public static function castNumberFormatter(\NumberFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
+ {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(),
+ Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(),
+ ];
+
+ if ($filter & Caster::EXCLUDE_VERBOSE) {
+ $stub->cut += 3;
+
+ return self::castError($c, $a);
+ }
+
+ $a += [
+ Caster::PREFIX_VIRTUAL.'attributes' => new EnumStub(
+ [
+ 'PARSE_INT_ONLY' => $c->getAttribute(\NumberFormatter::PARSE_INT_ONLY),
+ 'GROUPING_USED' => $c->getAttribute(\NumberFormatter::GROUPING_USED),
+ 'DECIMAL_ALWAYS_SHOWN' => $c->getAttribute(\NumberFormatter::DECIMAL_ALWAYS_SHOWN),
+ 'MAX_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_INTEGER_DIGITS),
+ 'MIN_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_INTEGER_DIGITS),
+ 'INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::INTEGER_DIGITS),
+ 'MAX_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_FRACTION_DIGITS),
+ 'MIN_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_FRACTION_DIGITS),
+ 'FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::FRACTION_DIGITS),
+ 'MULTIPLIER' => $c->getAttribute(\NumberFormatter::MULTIPLIER),
+ 'GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::GROUPING_SIZE),
+ 'ROUNDING_MODE' => $c->getAttribute(\NumberFormatter::ROUNDING_MODE),
+ 'ROUNDING_INCREMENT' => $c->getAttribute(\NumberFormatter::ROUNDING_INCREMENT),
+ 'FORMAT_WIDTH' => $c->getAttribute(\NumberFormatter::FORMAT_WIDTH),
+ 'PADDING_POSITION' => $c->getAttribute(\NumberFormatter::PADDING_POSITION),
+ 'SECONDARY_GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::SECONDARY_GROUPING_SIZE),
+ 'SIGNIFICANT_DIGITS_USED' => $c->getAttribute(\NumberFormatter::SIGNIFICANT_DIGITS_USED),
+ 'MIN_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_SIGNIFICANT_DIGITS),
+ 'MAX_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_SIGNIFICANT_DIGITS),
+ 'LENIENT_PARSE' => $c->getAttribute(\NumberFormatter::LENIENT_PARSE),
+ ]
+ ),
+ Caster::PREFIX_VIRTUAL.'text_attributes' => new EnumStub(
+ [
+ 'POSITIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_PREFIX),
+ 'POSITIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_SUFFIX),
+ 'NEGATIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_PREFIX),
+ 'NEGATIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_SUFFIX),
+ 'PADDING_CHARACTER' => $c->getTextAttribute(\NumberFormatter::PADDING_CHARACTER),
+ 'CURRENCY_CODE' => $c->getTextAttribute(\NumberFormatter::CURRENCY_CODE),
+ 'DEFAULT_RULESET' => $c->getTextAttribute(\NumberFormatter::DEFAULT_RULESET),
+ 'PUBLIC_RULESETS' => $c->getTextAttribute(\NumberFormatter::PUBLIC_RULESETS),
+ ]
+ ),
+ Caster::PREFIX_VIRTUAL.'symbols' => new EnumStub(
+ [
+ 'DECIMAL_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL),
+ 'GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL),
+ 'PATTERN_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::PATTERN_SEPARATOR_SYMBOL),
+ 'PERCENT_SYMBOL' => $c->getSymbol(\NumberFormatter::PERCENT_SYMBOL),
+ 'ZERO_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::ZERO_DIGIT_SYMBOL),
+ 'DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::DIGIT_SYMBOL),
+ 'MINUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::MINUS_SIGN_SYMBOL),
+ 'PLUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::PLUS_SIGN_SYMBOL),
+ 'CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::CURRENCY_SYMBOL),
+ 'INTL_CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::INTL_CURRENCY_SYMBOL),
+ 'MONETARY_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL),
+ 'EXPONENTIAL_SYMBOL' => $c->getSymbol(\NumberFormatter::EXPONENTIAL_SYMBOL),
+ 'PERMILL_SYMBOL' => $c->getSymbol(\NumberFormatter::PERMILL_SYMBOL),
+ 'PAD_ESCAPE_SYMBOL' => $c->getSymbol(\NumberFormatter::PAD_ESCAPE_SYMBOL),
+ 'INFINITY_SYMBOL' => $c->getSymbol(\NumberFormatter::INFINITY_SYMBOL),
+ 'NAN_SYMBOL' => $c->getSymbol(\NumberFormatter::NAN_SYMBOL),
+ 'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL),
+ 'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL),
+ ]
+ ),
+ ];
+
+ return self::castError($c, $a);
+ }
+
+ public static function castIntlTimeZone(\IntlTimeZone $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'display_name' => $c->getDisplayName(),
+ Caster::PREFIX_VIRTUAL.'id' => $c->getID(),
+ Caster::PREFIX_VIRTUAL.'raw_offset' => $c->getRawOffset(),
+ ];
+
+ if ($c->useDaylightTime()) {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'dst_savings' => $c->getDSTSavings(),
+ ];
+ }
+
+ return self::castError($c, $a);
+ }
+
+ public static function castIntlCalendar(\IntlCalendar $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
+ {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'type' => $c->getType(),
+ Caster::PREFIX_VIRTUAL.'first_day_of_week' => $c->getFirstDayOfWeek(),
+ Caster::PREFIX_VIRTUAL.'minimal_days_in_first_week' => $c->getMinimalDaysInFirstWeek(),
+ Caster::PREFIX_VIRTUAL.'repeated_wall_time_option' => $c->getRepeatedWallTimeOption(),
+ Caster::PREFIX_VIRTUAL.'skipped_wall_time_option' => $c->getSkippedWallTimeOption(),
+ Caster::PREFIX_VIRTUAL.'time' => $c->getTime(),
+ Caster::PREFIX_VIRTUAL.'in_daylight_time' => $c->inDaylightTime(),
+ Caster::PREFIX_VIRTUAL.'is_lenient' => $c->isLenient(),
+ Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(),
+ ];
+
+ return self::castError($c, $a);
+ }
+
+ public static function castIntlDateFormatter(\IntlDateFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
+ {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(),
+ Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(),
+ Caster::PREFIX_VIRTUAL.'calendar' => $c->getCalendar(),
+ Caster::PREFIX_VIRTUAL.'time_zone_id' => $c->getTimeZoneId(),
+ Caster::PREFIX_VIRTUAL.'time_type' => $c->getTimeType(),
+ Caster::PREFIX_VIRTUAL.'date_type' => $c->getDateType(),
+ Caster::PREFIX_VIRTUAL.'calendar_object' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getCalendarObject()) : $c->getCalendarObject(),
+ Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(),
+ ];
+
+ return self::castError($c, $a);
+ }
+
+ private static function castError(object $c, array $a): array
+ {
+ if ($errorCode = $c->getErrorCode()) {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'error_code' => $errorCode,
+ Caster::PREFIX_VIRTUAL.'error_message' => $c->getErrorMessage(),
+ ];
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/LinkStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/LinkStub.php
new file mode 100644
index 0000000..7e07803
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/LinkStub.php
@@ -0,0 +1,108 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+/**
+ * Represents a file or a URL.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class LinkStub extends ConstStub
+{
+ public $inVendor = false;
+
+ private static $vendorRoots;
+ private static $composerRoots;
+
+ public function __construct(string $label, int $line = 0, string $href = null)
+ {
+ $this->value = $label;
+
+ if (null === $href) {
+ $href = $label;
+ }
+ if (!\is_string($href)) {
+ return;
+ }
+ if (str_starts_with($href, 'file://')) {
+ if ($href === $label) {
+ $label = substr($label, 7);
+ }
+ $href = substr($href, 7);
+ } elseif (str_contains($href, '://')) {
+ $this->attr['href'] = $href;
+
+ return;
+ }
+ if (!is_file($href)) {
+ return;
+ }
+ if ($line) {
+ $this->attr['line'] = $line;
+ }
+ if ($label !== $this->attr['file'] = realpath($href) ?: $href) {
+ return;
+ }
+ if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) {
+ $this->attr['ellipsis'] = \strlen($href) - \strlen($composerRoot) + 1;
+ $this->attr['ellipsis-type'] = 'path';
+ $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + \strlen(implode('', \array_slice(explode(\DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0);
+ } elseif (3 < \count($ellipsis = explode(\DIRECTORY_SEPARATOR, $href))) {
+ $this->attr['ellipsis'] = 2 + \strlen(implode('', \array_slice($ellipsis, -2)));
+ $this->attr['ellipsis-type'] = 'path';
+ $this->attr['ellipsis-tail'] = 1;
+ }
+ }
+
+ private function getComposerRoot(string $file, bool &$inVendor)
+ {
+ if (null === self::$vendorRoots) {
+ self::$vendorRoots = [];
+
+ foreach (get_declared_classes() as $class) {
+ if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) {
+ $r = new \ReflectionClass($class);
+ $v = \dirname($r->getFileName(), 2);
+ if (is_file($v.'/composer/installed.json')) {
+ self::$vendorRoots[] = $v.\DIRECTORY_SEPARATOR;
+ }
+ }
+ }
+ }
+ $inVendor = false;
+
+ if (isset(self::$composerRoots[$dir = \dirname($file)])) {
+ return self::$composerRoots[$dir];
+ }
+
+ foreach (self::$vendorRoots as $root) {
+ if ($inVendor = str_starts_with($file, $root)) {
+ return $root;
+ }
+ }
+
+ $parent = $dir;
+ while (!@is_file($parent.'/composer.json')) {
+ if (!@file_exists($parent)) {
+ // open_basedir restriction in effect
+ break;
+ }
+ if ($parent === \dirname($parent)) {
+ return self::$composerRoots[$dir] = false;
+ }
+
+ $parent = \dirname($parent);
+ }
+
+ return self::$composerRoots[$dir] = $parent.\DIRECTORY_SEPARATOR;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/MemcachedCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/MemcachedCaster.php
new file mode 100644
index 0000000..cfef19a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/MemcachedCaster.php
@@ -0,0 +1,81 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>
+ *
+ * @final
+ */
+class MemcachedCaster
+{
+ private static $optionConstants;
+ private static $defaultOptions;
+
+ public static function castMemcached(\Memcached $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'servers' => $c->getServerList(),
+ Caster::PREFIX_VIRTUAL.'options' => new EnumStub(
+ self::getNonDefaultOptions($c)
+ ),
+ ];
+
+ return $a;
+ }
+
+ private static function getNonDefaultOptions(\Memcached $c): array
+ {
+ self::$defaultOptions = self::$defaultOptions ?? self::discoverDefaultOptions();
+ self::$optionConstants = self::$optionConstants ?? self::getOptionConstants();
+
+ $nonDefaultOptions = [];
+ foreach (self::$optionConstants as $constantKey => $value) {
+ if (self::$defaultOptions[$constantKey] !== $option = $c->getOption($value)) {
+ $nonDefaultOptions[$constantKey] = $option;
+ }
+ }
+
+ return $nonDefaultOptions;
+ }
+
+ private static function discoverDefaultOptions(): array
+ {
+ $defaultMemcached = new \Memcached();
+ $defaultMemcached->addServer('127.0.0.1', 11211);
+
+ $defaultOptions = [];
+ self::$optionConstants = self::$optionConstants ?? self::getOptionConstants();
+
+ foreach (self::$optionConstants as $constantKey => $value) {
+ $defaultOptions[$constantKey] = $defaultMemcached->getOption($value);
+ }
+
+ return $defaultOptions;
+ }
+
+ private static function getOptionConstants(): array
+ {
+ $reflectedMemcached = new \ReflectionClass(\Memcached::class);
+
+ $optionConstants = [];
+ foreach ($reflectedMemcached->getConstants() as $constantKey => $value) {
+ if (str_starts_with($constantKey, 'OPT_')) {
+ $optionConstants[$constantKey] = $value;
+ }
+ }
+
+ return $optionConstants;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/PdoCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/PdoCaster.php
new file mode 100644
index 0000000..140473b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/PdoCaster.php
@@ -0,0 +1,122 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts PDO related classes to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class PdoCaster
+{
+ private const PDO_ATTRIBUTES = [
+ 'CASE' => [
+ \PDO::CASE_LOWER => 'LOWER',
+ \PDO::CASE_NATURAL => 'NATURAL',
+ \PDO::CASE_UPPER => 'UPPER',
+ ],
+ 'ERRMODE' => [
+ \PDO::ERRMODE_SILENT => 'SILENT',
+ \PDO::ERRMODE_WARNING => 'WARNING',
+ \PDO::ERRMODE_EXCEPTION => 'EXCEPTION',
+ ],
+ 'TIMEOUT',
+ 'PREFETCH',
+ 'AUTOCOMMIT',
+ 'PERSISTENT',
+ 'DRIVER_NAME',
+ 'SERVER_INFO',
+ 'ORACLE_NULLS' => [
+ \PDO::NULL_NATURAL => 'NATURAL',
+ \PDO::NULL_EMPTY_STRING => 'EMPTY_STRING',
+ \PDO::NULL_TO_STRING => 'TO_STRING',
+ ],
+ 'CLIENT_VERSION',
+ 'SERVER_VERSION',
+ 'STATEMENT_CLASS',
+ 'EMULATE_PREPARES',
+ 'CONNECTION_STATUS',
+ 'STRINGIFY_FETCHES',
+ 'DEFAULT_FETCH_MODE' => [
+ \PDO::FETCH_ASSOC => 'ASSOC',
+ \PDO::FETCH_BOTH => 'BOTH',
+ \PDO::FETCH_LAZY => 'LAZY',
+ \PDO::FETCH_NUM => 'NUM',
+ \PDO::FETCH_OBJ => 'OBJ',
+ ],
+ ];
+
+ public static function castPdo(\PDO $c, array $a, Stub $stub, bool $isNested)
+ {
+ $attr = [];
+ $errmode = $c->getAttribute(\PDO::ATTR_ERRMODE);
+ $c->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+
+ foreach (self::PDO_ATTRIBUTES as $k => $v) {
+ if (!isset($k[0])) {
+ $k = $v;
+ $v = [];
+ }
+
+ try {
+ $attr[$k] = 'ERRMODE' === $k ? $errmode : $c->getAttribute(\constant('PDO::ATTR_'.$k));
+ if ($v && isset($v[$attr[$k]])) {
+ $attr[$k] = new ConstStub($v[$attr[$k]], $attr[$k]);
+ }
+ } catch (\Exception $e) {
+ }
+ }
+ if (isset($attr[$k = 'STATEMENT_CLASS'][1])) {
+ if ($attr[$k][1]) {
+ $attr[$k][1] = new ArgsStub($attr[$k][1], '__construct', $attr[$k][0]);
+ }
+ $attr[$k][0] = new ClassStub($attr[$k][0]);
+ }
+
+ $prefix = Caster::PREFIX_VIRTUAL;
+ $a += [
+ $prefix.'inTransaction' => method_exists($c, 'inTransaction'),
+ $prefix.'errorInfo' => $c->errorInfo(),
+ $prefix.'attributes' => new EnumStub($attr),
+ ];
+
+ if ($a[$prefix.'inTransaction']) {
+ $a[$prefix.'inTransaction'] = $c->inTransaction();
+ } else {
+ unset($a[$prefix.'inTransaction']);
+ }
+
+ if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) {
+ unset($a[$prefix.'errorInfo']);
+ }
+
+ $c->setAttribute(\PDO::ATTR_ERRMODE, $errmode);
+
+ return $a;
+ }
+
+ public static function castPdoStatement(\PDOStatement $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+ $a[$prefix.'errorInfo'] = $c->errorInfo();
+
+ if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) {
+ unset($a[$prefix.'errorInfo']);
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/PgSqlCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/PgSqlCaster.php
new file mode 100644
index 0000000..d8e5b52
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/PgSqlCaster.php
@@ -0,0 +1,156 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts pqsql resources to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class PgSqlCaster
+{
+ private const PARAM_CODES = [
+ 'server_encoding',
+ 'client_encoding',
+ 'is_superuser',
+ 'session_authorization',
+ 'DateStyle',
+ 'TimeZone',
+ 'IntervalStyle',
+ 'integer_datetimes',
+ 'application_name',
+ 'standard_conforming_strings',
+ ];
+
+ private const TRANSACTION_STATUS = [
+ \PGSQL_TRANSACTION_IDLE => 'PGSQL_TRANSACTION_IDLE',
+ \PGSQL_TRANSACTION_ACTIVE => 'PGSQL_TRANSACTION_ACTIVE',
+ \PGSQL_TRANSACTION_INTRANS => 'PGSQL_TRANSACTION_INTRANS',
+ \PGSQL_TRANSACTION_INERROR => 'PGSQL_TRANSACTION_INERROR',
+ \PGSQL_TRANSACTION_UNKNOWN => 'PGSQL_TRANSACTION_UNKNOWN',
+ ];
+
+ private const RESULT_STATUS = [
+ \PGSQL_EMPTY_QUERY => 'PGSQL_EMPTY_QUERY',
+ \PGSQL_COMMAND_OK => 'PGSQL_COMMAND_OK',
+ \PGSQL_TUPLES_OK => 'PGSQL_TUPLES_OK',
+ \PGSQL_COPY_OUT => 'PGSQL_COPY_OUT',
+ \PGSQL_COPY_IN => 'PGSQL_COPY_IN',
+ \PGSQL_BAD_RESPONSE => 'PGSQL_BAD_RESPONSE',
+ \PGSQL_NONFATAL_ERROR => 'PGSQL_NONFATAL_ERROR',
+ \PGSQL_FATAL_ERROR => 'PGSQL_FATAL_ERROR',
+ ];
+
+ private const DIAG_CODES = [
+ 'severity' => \PGSQL_DIAG_SEVERITY,
+ 'sqlstate' => \PGSQL_DIAG_SQLSTATE,
+ 'message' => \PGSQL_DIAG_MESSAGE_PRIMARY,
+ 'detail' => \PGSQL_DIAG_MESSAGE_DETAIL,
+ 'hint' => \PGSQL_DIAG_MESSAGE_HINT,
+ 'statement position' => \PGSQL_DIAG_STATEMENT_POSITION,
+ 'internal position' => \PGSQL_DIAG_INTERNAL_POSITION,
+ 'internal query' => \PGSQL_DIAG_INTERNAL_QUERY,
+ 'context' => \PGSQL_DIAG_CONTEXT,
+ 'file' => \PGSQL_DIAG_SOURCE_FILE,
+ 'line' => \PGSQL_DIAG_SOURCE_LINE,
+ 'function' => \PGSQL_DIAG_SOURCE_FUNCTION,
+ ];
+
+ public static function castLargeObject($lo, array $a, Stub $stub, bool $isNested)
+ {
+ $a['seek position'] = pg_lo_tell($lo);
+
+ return $a;
+ }
+
+ public static function castLink($link, array $a, Stub $stub, bool $isNested)
+ {
+ $a['status'] = pg_connection_status($link);
+ $a['status'] = new ConstStub(\PGSQL_CONNECTION_OK === $a['status'] ? 'PGSQL_CONNECTION_OK' : 'PGSQL_CONNECTION_BAD', $a['status']);
+ $a['busy'] = pg_connection_busy($link);
+
+ $a['transaction'] = pg_transaction_status($link);
+ if (isset(self::TRANSACTION_STATUS[$a['transaction']])) {
+ $a['transaction'] = new ConstStub(self::TRANSACTION_STATUS[$a['transaction']], $a['transaction']);
+ }
+
+ $a['pid'] = pg_get_pid($link);
+ $a['last error'] = pg_last_error($link);
+ $a['last notice'] = pg_last_notice($link);
+ $a['host'] = pg_host($link);
+ $a['port'] = pg_port($link);
+ $a['dbname'] = pg_dbname($link);
+ $a['options'] = pg_options($link);
+ $a['version'] = pg_version($link);
+
+ foreach (self::PARAM_CODES as $v) {
+ if (false !== $s = pg_parameter_status($link, $v)) {
+ $a['param'][$v] = $s;
+ }
+ }
+
+ $a['param']['client_encoding'] = pg_client_encoding($link);
+ $a['param'] = new EnumStub($a['param']);
+
+ return $a;
+ }
+
+ public static function castResult($result, array $a, Stub $stub, bool $isNested)
+ {
+ $a['num rows'] = pg_num_rows($result);
+ $a['status'] = pg_result_status($result);
+ if (isset(self::RESULT_STATUS[$a['status']])) {
+ $a['status'] = new ConstStub(self::RESULT_STATUS[$a['status']], $a['status']);
+ }
+ $a['command-completion tag'] = pg_result_status($result, \PGSQL_STATUS_STRING);
+
+ if (-1 === $a['num rows']) {
+ foreach (self::DIAG_CODES as $k => $v) {
+ $a['error'][$k] = pg_result_error_field($result, $v);
+ }
+ }
+
+ $a['affected rows'] = pg_affected_rows($result);
+ $a['last OID'] = pg_last_oid($result);
+
+ $fields = pg_num_fields($result);
+
+ for ($i = 0; $i < $fields; ++$i) {
+ $field = [
+ 'name' => pg_field_name($result, $i),
+ 'table' => sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, true)),
+ 'type' => sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)),
+ 'nullable' => (bool) pg_field_is_null($result, $i),
+ 'storage' => pg_field_size($result, $i).' bytes',
+ 'display' => pg_field_prtlen($result, $i).' chars',
+ ];
+ if (' (OID: )' === $field['table']) {
+ $field['table'] = null;
+ }
+ if ('-1 bytes' === $field['storage']) {
+ $field['storage'] = 'variable size';
+ } elseif ('1 bytes' === $field['storage']) {
+ $field['storage'] = '1 byte';
+ }
+ if ('1 chars' === $field['display']) {
+ $field['display'] = '1 char';
+ }
+ $a['fields'][] = new EnumStub($field);
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php
new file mode 100644
index 0000000..e712019
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use ProxyManager\Proxy\ProxyInterface;
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class ProxyManagerCaster
+{
+ public static function castProxy(ProxyInterface $c, array $a, Stub $stub, bool $isNested)
+ {
+ if ($parent = get_parent_class($c)) {
+ $stub->class .= ' - '.$parent;
+ }
+ $stub->class .= '@proxy';
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/RdKafkaCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/RdKafkaCaster.php
new file mode 100644
index 0000000..db4bba8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/RdKafkaCaster.php
@@ -0,0 +1,186 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use RdKafka\Conf;
+use RdKafka\Exception as RdKafkaException;
+use RdKafka\KafkaConsumer;
+use RdKafka\Message;
+use RdKafka\Metadata\Broker as BrokerMetadata;
+use RdKafka\Metadata\Collection as CollectionMetadata;
+use RdKafka\Metadata\Partition as PartitionMetadata;
+use RdKafka\Metadata\Topic as TopicMetadata;
+use RdKafka\Topic;
+use RdKafka\TopicConf;
+use RdKafka\TopicPartition;
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts RdKafka related classes to array representation.
+ *
+ * @author Romain Neutron <imprec@gmail.com>
+ */
+class RdKafkaCaster
+{
+ public static function castKafkaConsumer(KafkaConsumer $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ try {
+ $assignment = $c->getAssignment();
+ } catch (RdKafkaException $e) {
+ $assignment = [];
+ }
+
+ $a += [
+ $prefix.'subscription' => $c->getSubscription(),
+ $prefix.'assignment' => $assignment,
+ ];
+
+ $a += self::extractMetadata($c);
+
+ return $a;
+ }
+
+ public static function castTopic(Topic $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'name' => $c->getName(),
+ ];
+
+ return $a;
+ }
+
+ public static function castTopicPartition(TopicPartition $c, array $a)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'offset' => $c->getOffset(),
+ $prefix.'partition' => $c->getPartition(),
+ $prefix.'topic' => $c->getTopic(),
+ ];
+
+ return $a;
+ }
+
+ public static function castMessage(Message $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'errstr' => $c->errstr(),
+ ];
+
+ return $a;
+ }
+
+ public static function castConf(Conf $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ foreach ($c->dump() as $key => $value) {
+ $a[$prefix.$key] = $value;
+ }
+
+ return $a;
+ }
+
+ public static function castTopicConf(TopicConf $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ foreach ($c->dump() as $key => $value) {
+ $a[$prefix.$key] = $value;
+ }
+
+ return $a;
+ }
+
+ public static function castRdKafka(\RdKafka $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'out_q_len' => $c->getOutQLen(),
+ ];
+
+ $a += self::extractMetadata($c);
+
+ return $a;
+ }
+
+ public static function castCollectionMetadata(CollectionMetadata $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a += iterator_to_array($c);
+
+ return $a;
+ }
+
+ public static function castTopicMetadata(TopicMetadata $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'name' => $c->getTopic(),
+ $prefix.'partitions' => $c->getPartitions(),
+ ];
+
+ return $a;
+ }
+
+ public static function castPartitionMetadata(PartitionMetadata $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'id' => $c->getId(),
+ $prefix.'err' => $c->getErr(),
+ $prefix.'leader' => $c->getLeader(),
+ ];
+
+ return $a;
+ }
+
+ public static function castBrokerMetadata(BrokerMetadata $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ $a += [
+ $prefix.'id' => $c->getId(),
+ $prefix.'host' => $c->getHost(),
+ $prefix.'port' => $c->getPort(),
+ ];
+
+ return $a;
+ }
+
+ private static function extractMetadata($c)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ try {
+ $m = $c->getMetadata(true, null, 500);
+ } catch (RdKafkaException $e) {
+ return [];
+ }
+
+ return [
+ $prefix.'orig_broker_id' => $m->getOrigBrokerId(),
+ $prefix.'orig_broker_name' => $m->getOrigBrokerName(),
+ $prefix.'brokers' => $m->getBrokers(),
+ $prefix.'topics' => $m->getTopics(),
+ ];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/RedisCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/RedisCaster.php
new file mode 100644
index 0000000..8f97eaa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/RedisCaster.php
@@ -0,0 +1,152 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts Redis class from ext-redis to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class RedisCaster
+{
+ private const SERIALIZERS = [
+ \Redis::SERIALIZER_NONE => 'NONE',
+ \Redis::SERIALIZER_PHP => 'PHP',
+ 2 => 'IGBINARY', // Optional Redis::SERIALIZER_IGBINARY
+ ];
+
+ private const MODES = [
+ \Redis::ATOMIC => 'ATOMIC',
+ \Redis::MULTI => 'MULTI',
+ \Redis::PIPELINE => 'PIPELINE',
+ ];
+
+ private const COMPRESSION_MODES = [
+ 0 => 'NONE', // Redis::COMPRESSION_NONE
+ 1 => 'LZF', // Redis::COMPRESSION_LZF
+ ];
+
+ private const FAILOVER_OPTIONS = [
+ \RedisCluster::FAILOVER_NONE => 'NONE',
+ \RedisCluster::FAILOVER_ERROR => 'ERROR',
+ \RedisCluster::FAILOVER_DISTRIBUTE => 'DISTRIBUTE',
+ \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES => 'DISTRIBUTE_SLAVES',
+ ];
+
+ public static function castRedis(\Redis $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ if (!$connected = $c->isConnected()) {
+ return $a + [
+ $prefix.'isConnected' => $connected,
+ ];
+ }
+
+ $mode = $c->getMode();
+
+ return $a + [
+ $prefix.'isConnected' => $connected,
+ $prefix.'host' => $c->getHost(),
+ $prefix.'port' => $c->getPort(),
+ $prefix.'auth' => $c->getAuth(),
+ $prefix.'mode' => isset(self::MODES[$mode]) ? new ConstStub(self::MODES[$mode], $mode) : $mode,
+ $prefix.'dbNum' => $c->getDbNum(),
+ $prefix.'timeout' => $c->getTimeout(),
+ $prefix.'lastError' => $c->getLastError(),
+ $prefix.'persistentId' => $c->getPersistentID(),
+ $prefix.'options' => self::getRedisOptions($c),
+ ];
+ }
+
+ public static function castRedisArray(\RedisArray $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ return $a + [
+ $prefix.'hosts' => $c->_hosts(),
+ $prefix.'function' => ClassStub::wrapCallable($c->_function()),
+ $prefix.'lastError' => $c->getLastError(),
+ $prefix.'options' => self::getRedisOptions($c),
+ ];
+ }
+
+ public static function castRedisCluster(\RedisCluster $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+ $failover = $c->getOption(\RedisCluster::OPT_SLAVE_FAILOVER);
+
+ $a += [
+ $prefix.'_masters' => $c->_masters(),
+ $prefix.'_redir' => $c->_redir(),
+ $prefix.'mode' => new ConstStub($c->getMode() ? 'MULTI' : 'ATOMIC', $c->getMode()),
+ $prefix.'lastError' => $c->getLastError(),
+ $prefix.'options' => self::getRedisOptions($c, [
+ 'SLAVE_FAILOVER' => isset(self::FAILOVER_OPTIONS[$failover]) ? new ConstStub(self::FAILOVER_OPTIONS[$failover], $failover) : $failover,
+ ]),
+ ];
+
+ return $a;
+ }
+
+ /**
+ * @param \Redis|\RedisArray|\RedisCluster $redis
+ */
+ private static function getRedisOptions($redis, array $options = []): EnumStub
+ {
+ $serializer = $redis->getOption(\Redis::OPT_SERIALIZER);
+ if (\is_array($serializer)) {
+ foreach ($serializer as &$v) {
+ if (isset(self::SERIALIZERS[$v])) {
+ $v = new ConstStub(self::SERIALIZERS[$v], $v);
+ }
+ }
+ } elseif (isset(self::SERIALIZERS[$serializer])) {
+ $serializer = new ConstStub(self::SERIALIZERS[$serializer], $serializer);
+ }
+
+ $compression = \defined('Redis::OPT_COMPRESSION') ? $redis->getOption(\Redis::OPT_COMPRESSION) : 0;
+ if (\is_array($compression)) {
+ foreach ($compression as &$v) {
+ if (isset(self::COMPRESSION_MODES[$v])) {
+ $v = new ConstStub(self::COMPRESSION_MODES[$v], $v);
+ }
+ }
+ } elseif (isset(self::COMPRESSION_MODES[$compression])) {
+ $compression = new ConstStub(self::COMPRESSION_MODES[$compression], $compression);
+ }
+
+ $retry = \defined('Redis::OPT_SCAN') ? $redis->getOption(\Redis::OPT_SCAN) : 0;
+ if (\is_array($retry)) {
+ foreach ($retry as &$v) {
+ $v = new ConstStub($v ? 'RETRY' : 'NORETRY', $v);
+ }
+ } else {
+ $retry = new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry);
+ }
+
+ $options += [
+ 'TCP_KEEPALIVE' => \defined('Redis::OPT_TCP_KEEPALIVE') ? $redis->getOption(\Redis::OPT_TCP_KEEPALIVE) : 0,
+ 'READ_TIMEOUT' => $redis->getOption(\Redis::OPT_READ_TIMEOUT),
+ 'COMPRESSION' => $compression,
+ 'SERIALIZER' => $serializer,
+ 'PREFIX' => $redis->getOption(\Redis::OPT_PREFIX),
+ 'SCAN' => $retry,
+ ];
+
+ return new EnumStub($options);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ReflectionCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ReflectionCaster.php
new file mode 100644
index 0000000..1781f46
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ReflectionCaster.php
@@ -0,0 +1,438 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts Reflector related classes to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class ReflectionCaster
+{
+ public const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__.'::unsetClosureFileInfo'];
+
+ private const EXTRA_MAP = [
+ 'docComment' => 'getDocComment',
+ 'extension' => 'getExtensionName',
+ 'isDisabled' => 'isDisabled',
+ 'isDeprecated' => 'isDeprecated',
+ 'isInternal' => 'isInternal',
+ 'isUserDefined' => 'isUserDefined',
+ 'isGenerator' => 'isGenerator',
+ 'isVariadic' => 'isVariadic',
+ ];
+
+ public static function castClosure(\Closure $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+ $c = new \ReflectionFunction($c);
+
+ $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter);
+
+ if (!str_contains($c->name, '{closure}')) {
+ $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name;
+ unset($a[$prefix.'class']);
+ }
+ unset($a[$prefix.'extra']);
+
+ $stub->class .= self::getSignature($a);
+
+ if ($f = $c->getFileName()) {
+ $stub->attr['file'] = $f;
+ $stub->attr['line'] = $c->getStartLine();
+ }
+
+ unset($a[$prefix.'parameters']);
+
+ if ($filter & Caster::EXCLUDE_VERBOSE) {
+ $stub->cut += ($c->getFileName() ? 2 : 0) + \count($a);
+
+ return [];
+ }
+
+ if ($f) {
+ $a[$prefix.'file'] = new LinkStub($f, $c->getStartLine());
+ $a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();
+ }
+
+ return $a;
+ }
+
+ public static function unsetClosureFileInfo(\Closure $c, array $a)
+ {
+ unset($a[Caster::PREFIX_VIRTUAL.'file'], $a[Caster::PREFIX_VIRTUAL.'line']);
+
+ return $a;
+ }
+
+ public static function castGenerator(\Generator $c, array $a, Stub $stub, bool $isNested)
+ {
+ // Cannot create ReflectionGenerator based on a terminated Generator
+ try {
+ $reflectionGenerator = new \ReflectionGenerator($c);
+ } catch (\Exception $e) {
+ $a[Caster::PREFIX_VIRTUAL.'closed'] = true;
+
+ return $a;
+ }
+
+ return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested);
+ }
+
+ public static function castType(\ReflectionType $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ if ($c instanceof \ReflectionNamedType || \PHP_VERSION_ID < 80000) {
+ $a += [
+ $prefix.'name' => $c instanceof \ReflectionNamedType ? $c->getName() : (string) $c,
+ $prefix.'allowsNull' => $c->allowsNull(),
+ $prefix.'isBuiltin' => $c->isBuiltin(),
+ ];
+ } elseif ($c instanceof \ReflectionUnionType || $c instanceof \ReflectionIntersectionType) {
+ $a[$prefix.'allowsNull'] = $c->allowsNull();
+ self::addMap($a, $c, [
+ 'types' => 'getTypes',
+ ]);
+ } else {
+ $a[$prefix.'allowsNull'] = $c->allowsNull();
+ }
+
+ return $a;
+ }
+
+ public static function castAttribute(\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested)
+ {
+ self::addMap($a, $c, [
+ 'name' => 'getName',
+ 'arguments' => 'getArguments',
+ ]);
+
+ return $a;
+ }
+
+ public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ if ($c->getThis()) {
+ $a[$prefix.'this'] = new CutStub($c->getThis());
+ }
+ $function = $c->getFunction();
+ $frame = [
+ 'class' => $function->class ?? null,
+ 'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null,
+ 'function' => $function->name,
+ 'file' => $c->getExecutingFile(),
+ 'line' => $c->getExecutingLine(),
+ ];
+ if ($trace = $c->getTrace(\DEBUG_BACKTRACE_IGNORE_ARGS)) {
+ $function = new \ReflectionGenerator($c->getExecutingGenerator());
+ array_unshift($trace, [
+ 'function' => 'yield',
+ 'file' => $function->getExecutingFile(),
+ 'line' => $function->getExecutingLine() - 1,
+ ]);
+ $trace[] = $frame;
+ $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1);
+ } else {
+ $function = new FrameStub($frame, false, true);
+ $function = ExceptionCaster::castFrameStub($function, [], $function, true);
+ $a[$prefix.'executing'] = $function[$prefix.'src'];
+ }
+
+ $a[Caster::PREFIX_VIRTUAL.'closed'] = false;
+
+ return $a;
+ }
+
+ public static function castClass(\ReflectionClass $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ if ($n = \Reflection::getModifierNames($c->getModifiers())) {
+ $a[$prefix.'modifiers'] = implode(' ', $n);
+ }
+
+ self::addMap($a, $c, [
+ 'extends' => 'getParentClass',
+ 'implements' => 'getInterfaceNames',
+ 'constants' => 'getReflectionConstants',
+ ]);
+
+ foreach ($c->getProperties() as $n) {
+ $a[$prefix.'properties'][$n->name] = $n;
+ }
+
+ foreach ($c->getMethods() as $n) {
+ $a[$prefix.'methods'][$n->name] = $n;
+ }
+
+ self::addAttributes($a, $c, $prefix);
+
+ if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {
+ self::addExtra($a, $c);
+ }
+
+ return $a;
+ }
+
+ public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ self::addMap($a, $c, [
+ 'returnsReference' => 'returnsReference',
+ 'returnType' => 'getReturnType',
+ 'class' => 'getClosureScopeClass',
+ 'this' => 'getClosureThis',
+ ]);
+
+ if (isset($a[$prefix.'returnType'])) {
+ $v = $a[$prefix.'returnType'];
+ $v = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v;
+ $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType'] instanceof \ReflectionNamedType && $a[$prefix.'returnType']->allowsNull() && 'mixed' !== $v ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']);
+ }
+ if (isset($a[$prefix.'class'])) {
+ $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']);
+ }
+ if (isset($a[$prefix.'this'])) {
+ $a[$prefix.'this'] = new CutStub($a[$prefix.'this']);
+ }
+
+ foreach ($c->getParameters() as $v) {
+ $k = '$'.$v->name;
+ if ($v->isVariadic()) {
+ $k = '...'.$k;
+ }
+ if ($v->isPassedByReference()) {
+ $k = '&'.$k;
+ }
+ $a[$prefix.'parameters'][$k] = $v;
+ }
+ if (isset($a[$prefix.'parameters'])) {
+ $a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']);
+ }
+
+ self::addAttributes($a, $c, $prefix);
+
+ if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) {
+ foreach ($v as $k => &$v) {
+ if (\is_object($v)) {
+ $a[$prefix.'use']['$'.$k] = new CutStub($v);
+ } else {
+ $a[$prefix.'use']['$'.$k] = &$v;
+ }
+ }
+ unset($v);
+ $a[$prefix.'use'] = new EnumStub($a[$prefix.'use']);
+ }
+
+ if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {
+ self::addExtra($a, $c);
+ }
+
+ return $a;
+ }
+
+ public static function castClassConstant(\ReflectionClassConstant $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
+ $a[Caster::PREFIX_VIRTUAL.'value'] = $c->getValue();
+
+ self::addAttributes($a, $c);
+
+ return $a;
+ }
+
+ public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
+
+ return $a;
+ }
+
+ public static function castParameter(\ReflectionParameter $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ self::addMap($a, $c, [
+ 'position' => 'getPosition',
+ 'isVariadic' => 'isVariadic',
+ 'byReference' => 'isPassedByReference',
+ 'allowsNull' => 'allowsNull',
+ ]);
+
+ self::addAttributes($a, $c, $prefix);
+
+ if ($v = $c->getType()) {
+ $a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v;
+ }
+
+ if (isset($a[$prefix.'typeHint'])) {
+ $v = $a[$prefix.'typeHint'];
+ $a[$prefix.'typeHint'] = new ClassStub($v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']);
+ } else {
+ unset($a[$prefix.'allowsNull']);
+ }
+
+ try {
+ $a[$prefix.'default'] = $v = $c->getDefaultValue();
+ if ($c->isDefaultValueConstant()) {
+ $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v);
+ }
+ if (null === $v) {
+ unset($a[$prefix.'allowsNull']);
+ }
+ } catch (\ReflectionException $e) {
+ }
+
+ return $a;
+ }
+
+ public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
+
+ self::addAttributes($a, $c);
+ self::addExtra($a, $c);
+
+ return $a;
+ }
+
+ public static function castReference(\ReflectionReference $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a[Caster::PREFIX_VIRTUAL.'id'] = $c->getId();
+
+ return $a;
+ }
+
+ public static function castExtension(\ReflectionExtension $c, array $a, Stub $stub, bool $isNested)
+ {
+ self::addMap($a, $c, [
+ 'version' => 'getVersion',
+ 'dependencies' => 'getDependencies',
+ 'iniEntries' => 'getIniEntries',
+ 'isPersistent' => 'isPersistent',
+ 'isTemporary' => 'isTemporary',
+ 'constants' => 'getConstants',
+ 'functions' => 'getFunctions',
+ 'classes' => 'getClasses',
+ ]);
+
+ return $a;
+ }
+
+ public static function castZendExtension(\ReflectionZendExtension $c, array $a, Stub $stub, bool $isNested)
+ {
+ self::addMap($a, $c, [
+ 'version' => 'getVersion',
+ 'author' => 'getAuthor',
+ 'copyright' => 'getCopyright',
+ 'url' => 'getURL',
+ ]);
+
+ return $a;
+ }
+
+ public static function getSignature(array $a)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+ $signature = '';
+
+ if (isset($a[$prefix.'parameters'])) {
+ foreach ($a[$prefix.'parameters']->value as $k => $param) {
+ $signature .= ', ';
+ if ($type = $param->getType()) {
+ if (!$type instanceof \ReflectionNamedType) {
+ $signature .= $type.' ';
+ } else {
+ if (!$param->isOptional() && $param->allowsNull() && 'mixed' !== $type->getName()) {
+ $signature .= '?';
+ }
+ $signature .= substr(strrchr('\\'.$type->getName(), '\\'), 1).' ';
+ }
+ }
+ $signature .= $k;
+
+ if (!$param->isDefaultValueAvailable()) {
+ continue;
+ }
+ $v = $param->getDefaultValue();
+ $signature .= ' = ';
+
+ if ($param->isDefaultValueConstant()) {
+ $signature .= substr(strrchr('\\'.$param->getDefaultValueConstantName(), '\\'), 1);
+ } elseif (null === $v) {
+ $signature .= 'null';
+ } elseif (\is_array($v)) {
+ $signature .= $v ? '[…'.\count($v).']' : '[]';
+ } elseif (\is_string($v)) {
+ $signature .= 10 > \strlen($v) && !str_contains($v, '\\') ? "'{$v}'" : "'…".\strlen($v)."'";
+ } elseif (\is_bool($v)) {
+ $signature .= $v ? 'true' : 'false';
+ } else {
+ $signature .= $v;
+ }
+ }
+ }
+ $signature = (empty($a[$prefix.'returnsReference']) ? '' : '&').'('.substr($signature, 2).')';
+
+ if (isset($a[$prefix.'returnType'])) {
+ $signature .= ': '.substr(strrchr('\\'.$a[$prefix.'returnType'], '\\'), 1);
+ }
+
+ return $signature;
+ }
+
+ private static function addExtra(array &$a, \Reflector $c)
+ {
+ $x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : [];
+
+ if (method_exists($c, 'getFileName') && $m = $c->getFileName()) {
+ $x['file'] = new LinkStub($m, $c->getStartLine());
+ $x['line'] = $c->getStartLine().' to '.$c->getEndLine();
+ }
+
+ self::addMap($x, $c, self::EXTRA_MAP, '');
+
+ if ($x) {
+ $a[Caster::PREFIX_VIRTUAL.'extra'] = new EnumStub($x);
+ }
+ }
+
+ private static function addMap(array &$a, object $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL)
+ {
+ foreach ($map as $k => $m) {
+ if (\PHP_VERSION_ID >= 80000 && 'isDisabled' === $k) {
+ continue;
+ }
+
+ if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) {
+ $a[$prefix.$k] = $m instanceof \Reflector ? $m->name : $m;
+ }
+ }
+ }
+
+ private static function addAttributes(array &$a, \Reflector $c, string $prefix = Caster::PREFIX_VIRTUAL): void
+ {
+ if (\PHP_VERSION_ID >= 80000) {
+ foreach ($c->getAttributes() as $n) {
+ $a[$prefix.'attributes'][] = $n;
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ResourceCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ResourceCaster.php
new file mode 100644
index 0000000..6ae9085
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ResourceCaster.php
@@ -0,0 +1,105 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts common resource types to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class ResourceCaster
+{
+ /**
+ * @param \CurlHandle|resource $h
+ *
+ * @return array
+ */
+ public static function castCurl($h, array $a, Stub $stub, bool $isNested)
+ {
+ return curl_getinfo($h);
+ }
+
+ public static function castDba($dba, array $a, Stub $stub, bool $isNested)
+ {
+ $list = dba_list();
+ $a['file'] = $list[(int) $dba];
+
+ return $a;
+ }
+
+ public static function castProcess($process, array $a, Stub $stub, bool $isNested)
+ {
+ return proc_get_status($process);
+ }
+
+ public static function castStream($stream, array $a, Stub $stub, bool $isNested)
+ {
+ $a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested);
+ if ($a['uri'] ?? false) {
+ $a['uri'] = new LinkStub($a['uri']);
+ }
+
+ return $a;
+ }
+
+ public static function castStreamContext($stream, array $a, Stub $stub, bool $isNested)
+ {
+ return @stream_context_get_params($stream) ?: $a;
+ }
+
+ public static function castGd($gd, array $a, Stub $stub, bool $isNested)
+ {
+ $a['size'] = imagesx($gd).'x'.imagesy($gd);
+ $a['trueColor'] = imageistruecolor($gd);
+
+ return $a;
+ }
+
+ public static function castMysqlLink($h, array $a, Stub $stub, bool $isNested)
+ {
+ $a['host'] = mysql_get_host_info($h);
+ $a['protocol'] = mysql_get_proto_info($h);
+ $a['server'] = mysql_get_server_info($h);
+
+ return $a;
+ }
+
+ public static function castOpensslX509($h, array $a, Stub $stub, bool $isNested)
+ {
+ $stub->cut = -1;
+ $info = openssl_x509_parse($h, false);
+
+ $pin = openssl_pkey_get_public($h);
+ $pin = openssl_pkey_get_details($pin)['key'];
+ $pin = \array_slice(explode("\n", $pin), 1, -2);
+ $pin = base64_decode(implode('', $pin));
+ $pin = base64_encode(hash('sha256', $pin, true));
+
+ $a += [
+ 'subject' => new EnumStub(array_intersect_key($info['subject'], ['organizationName' => true, 'commonName' => true])),
+ 'issuer' => new EnumStub(array_intersect_key($info['issuer'], ['organizationName' => true, 'commonName' => true])),
+ 'expiry' => new ConstStub(date(\DateTime::ISO8601, $info['validTo_time_t']), $info['validTo_time_t']),
+ 'fingerprint' => new EnumStub([
+ 'md5' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'md5')), 2, ':', true)),
+ 'sha1' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha1')), 2, ':', true)),
+ 'sha256' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha256')), 2, ':', true)),
+ 'pin-sha256' => new ConstStub($pin),
+ ]),
+ ];
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/SplCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/SplCaster.php
new file mode 100644
index 0000000..07f4451
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/SplCaster.php
@@ -0,0 +1,245 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts SPL related classes to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class SplCaster
+{
+ private const SPL_FILE_OBJECT_FLAGS = [
+ \SplFileObject::DROP_NEW_LINE => 'DROP_NEW_LINE',
+ \SplFileObject::READ_AHEAD => 'READ_AHEAD',
+ \SplFileObject::SKIP_EMPTY => 'SKIP_EMPTY',
+ \SplFileObject::READ_CSV => 'READ_CSV',
+ ];
+
+ public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, bool $isNested)
+ {
+ return self::castSplArray($c, $a, $stub, $isNested);
+ }
+
+ public static function castArrayIterator(\ArrayIterator $c, array $a, Stub $stub, bool $isNested)
+ {
+ return self::castSplArray($c, $a, $stub, $isNested);
+ }
+
+ public static function castHeap(\Iterator $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'heap' => iterator_to_array(clone $c),
+ ];
+
+ return $a;
+ }
+
+ public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a, Stub $stub, bool $isNested)
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+ $mode = $c->getIteratorMode();
+ $c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE);
+
+ $a += [
+ $prefix.'mode' => new ConstStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_DELETE) ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode),
+ $prefix.'dllist' => iterator_to_array($c),
+ ];
+ $c->setIteratorMode($mode);
+
+ return $a;
+ }
+
+ public static function castFileInfo(\SplFileInfo $c, array $a, Stub $stub, bool $isNested)
+ {
+ static $map = [
+ 'path' => 'getPath',
+ 'filename' => 'getFilename',
+ 'basename' => 'getBasename',
+ 'pathname' => 'getPathname',
+ 'extension' => 'getExtension',
+ 'realPath' => 'getRealPath',
+ 'aTime' => 'getATime',
+ 'mTime' => 'getMTime',
+ 'cTime' => 'getCTime',
+ 'inode' => 'getInode',
+ 'size' => 'getSize',
+ 'perms' => 'getPerms',
+ 'owner' => 'getOwner',
+ 'group' => 'getGroup',
+ 'type' => 'getType',
+ 'writable' => 'isWritable',
+ 'readable' => 'isReadable',
+ 'executable' => 'isExecutable',
+ 'file' => 'isFile',
+ 'dir' => 'isDir',
+ 'link' => 'isLink',
+ 'linkTarget' => 'getLinkTarget',
+ ];
+
+ $prefix = Caster::PREFIX_VIRTUAL;
+ unset($a["\0SplFileInfo\0fileName"]);
+ unset($a["\0SplFileInfo\0pathName"]);
+
+ if (\PHP_VERSION_ID < 80000) {
+ if (false === $c->getPathname()) {
+ $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state';
+
+ return $a;
+ }
+ } else {
+ try {
+ $c->isReadable();
+ } catch (\RuntimeException $e) {
+ if ('Object not initialized' !== $e->getMessage()) {
+ throw $e;
+ }
+
+ $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state';
+
+ return $a;
+ } catch (\Error $e) {
+ if ('Object not initialized' !== $e->getMessage()) {
+ throw $e;
+ }
+
+ $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state';
+
+ return $a;
+ }
+ }
+
+ foreach ($map as $key => $accessor) {
+ try {
+ $a[$prefix.$key] = $c->$accessor();
+ } catch (\Exception $e) {
+ }
+ }
+
+ if ($a[$prefix.'realPath'] ?? false) {
+ $a[$prefix.'realPath'] = new LinkStub($a[$prefix.'realPath']);
+ }
+
+ if (isset($a[$prefix.'perms'])) {
+ $a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']);
+ }
+
+ static $mapDate = ['aTime', 'mTime', 'cTime'];
+ foreach ($mapDate as $key) {
+ if (isset($a[$prefix.$key])) {
+ $a[$prefix.$key] = new ConstStub(date('Y-m-d H:i:s', $a[$prefix.$key]), $a[$prefix.$key]);
+ }
+ }
+
+ return $a;
+ }
+
+ public static function castFileObject(\SplFileObject $c, array $a, Stub $stub, bool $isNested)
+ {
+ static $map = [
+ 'csvControl' => 'getCsvControl',
+ 'flags' => 'getFlags',
+ 'maxLineLen' => 'getMaxLineLen',
+ 'fstat' => 'fstat',
+ 'eof' => 'eof',
+ 'key' => 'key',
+ ];
+
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ foreach ($map as $key => $accessor) {
+ try {
+ $a[$prefix.$key] = $c->$accessor();
+ } catch (\Exception $e) {
+ }
+ }
+
+ if (isset($a[$prefix.'flags'])) {
+ $flagsArray = [];
+ foreach (self::SPL_FILE_OBJECT_FLAGS as $value => $name) {
+ if ($a[$prefix.'flags'] & $value) {
+ $flagsArray[] = $name;
+ }
+ }
+ $a[$prefix.'flags'] = new ConstStub(implode('|', $flagsArray), $a[$prefix.'flags']);
+ }
+
+ if (isset($a[$prefix.'fstat'])) {
+ $a[$prefix.'fstat'] = new CutArrayStub($a[$prefix.'fstat'], ['dev', 'ino', 'nlink', 'rdev', 'blksize', 'blocks']);
+ }
+
+ return $a;
+ }
+
+ public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, bool $isNested)
+ {
+ $storage = [];
+ unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967
+ unset($a["\0SplObjectStorage\0storage"]);
+
+ $clone = clone $c;
+ foreach ($clone as $obj) {
+ $storage[] = [
+ 'object' => $obj,
+ 'info' => $clone->getInfo(),
+ ];
+ }
+
+ $a += [
+ Caster::PREFIX_VIRTUAL.'storage' => $storage,
+ ];
+
+ return $a;
+ }
+
+ public static function castOuterIterator(\OuterIterator $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a[Caster::PREFIX_VIRTUAL.'innerIterator'] = $c->getInnerIterator();
+
+ return $a;
+ }
+
+ public static function castWeakReference(\WeakReference $c, array $a, Stub $stub, bool $isNested)
+ {
+ $a[Caster::PREFIX_VIRTUAL.'object'] = $c->get();
+
+ return $a;
+ }
+
+ private static function castSplArray($c, array $a, Stub $stub, bool $isNested): array
+ {
+ $prefix = Caster::PREFIX_VIRTUAL;
+ $flags = $c->getFlags();
+
+ if (!($flags & \ArrayObject::STD_PROP_LIST)) {
+ $c->setFlags(\ArrayObject::STD_PROP_LIST);
+ $a = Caster::castObject($c, \get_class($c), method_exists($c, '__debugInfo'), $stub->class);
+ $c->setFlags($flags);
+ }
+ if (\PHP_VERSION_ID < 70400) {
+ $a[$prefix.'storage'] = $c->getArrayCopy();
+ }
+ $a += [
+ $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST),
+ $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS),
+ ];
+ if ($c instanceof \ArrayObject) {
+ $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass());
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/StubCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/StubCaster.php
new file mode 100644
index 0000000..32ead7c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/StubCaster.php
@@ -0,0 +1,84 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts a caster's Stub.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class StubCaster
+{
+ public static function castStub(Stub $c, array $a, Stub $stub, bool $isNested)
+ {
+ if ($isNested) {
+ $stub->type = $c->type;
+ $stub->class = $c->class;
+ $stub->value = $c->value;
+ $stub->handle = $c->handle;
+ $stub->cut = $c->cut;
+ $stub->attr = $c->attr;
+
+ if (Stub::TYPE_REF === $c->type && !$c->class && \is_string($c->value) && !preg_match('//u', $c->value)) {
+ $stub->type = Stub::TYPE_STRING;
+ $stub->class = Stub::STRING_BINARY;
+ }
+
+ $a = [];
+ }
+
+ return $a;
+ }
+
+ public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, bool $isNested)
+ {
+ return $isNested ? $c->preservedSubset : $a;
+ }
+
+ public static function cutInternals($obj, array $a, Stub $stub, bool $isNested)
+ {
+ if ($isNested) {
+ $stub->cut += \count($a);
+
+ return [];
+ }
+
+ return $a;
+ }
+
+ public static function castEnum(EnumStub $c, array $a, Stub $stub, bool $isNested)
+ {
+ if ($isNested) {
+ $stub->class = $c->dumpKeys ? '' : null;
+ $stub->handle = 0;
+ $stub->value = null;
+ $stub->cut = $c->cut;
+ $stub->attr = $c->attr;
+
+ $a = [];
+
+ if ($c->value) {
+ foreach (array_keys($c->value) as $k) {
+ $keys[] = !isset($k[0]) || "\0" !== $k[0] ? Caster::PREFIX_VIRTUAL.$k : $k;
+ }
+ // Preserve references with array_combine()
+ $a = array_combine($keys, $c->value);
+ }
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/SymfonyCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/SymfonyCaster.php
new file mode 100644
index 0000000..b7e1dd4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/SymfonyCaster.php
@@ -0,0 +1,69 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * @final
+ */
+class SymfonyCaster
+{
+ private const REQUEST_GETTERS = [
+ 'pathInfo' => 'getPathInfo',
+ 'requestUri' => 'getRequestUri',
+ 'baseUrl' => 'getBaseUrl',
+ 'basePath' => 'getBasePath',
+ 'method' => 'getMethod',
+ 'format' => 'getRequestFormat',
+ ];
+
+ public static function castRequest(Request $request, array $a, Stub $stub, bool $isNested)
+ {
+ $clone = null;
+
+ foreach (self::REQUEST_GETTERS as $prop => $getter) {
+ $key = Caster::PREFIX_PROTECTED.$prop;
+ if (\array_key_exists($key, $a) && null === $a[$key]) {
+ if (null === $clone) {
+ $clone = clone $request;
+ }
+ $a[Caster::PREFIX_VIRTUAL.$prop] = $clone->{$getter}();
+ }
+ }
+
+ return $a;
+ }
+
+ public static function castHttpClient($client, array $a, Stub $stub, bool $isNested)
+ {
+ $multiKey = sprintf("\0%s\0multi", \get_class($client));
+ if (isset($a[$multiKey])) {
+ $a[$multiKey] = new CutStub($a[$multiKey]);
+ }
+
+ return $a;
+ }
+
+ public static function castHttpClientResponse($response, array $a, Stub $stub, bool $isNested)
+ {
+ $stub->cut += \count($a);
+ $a = [];
+
+ foreach ($response->getInfo() as $k => $v) {
+ $a[Caster::PREFIX_VIRTUAL.$k] = $v;
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/TraceStub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/TraceStub.php
new file mode 100644
index 0000000..5eea1c8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/TraceStub.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Represents a backtrace as returned by debug_backtrace() or Exception->getTrace().
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class TraceStub extends Stub
+{
+ public $keepArgs;
+ public $sliceOffset;
+ public $sliceLength;
+ public $numberingOffset;
+
+ public function __construct(array $trace, bool $keepArgs = true, int $sliceOffset = 0, int $sliceLength = null, int $numberingOffset = 0)
+ {
+ $this->value = $trace;
+ $this->keepArgs = $keepArgs;
+ $this->sliceOffset = $sliceOffset;
+ $this->sliceLength = $sliceLength;
+ $this->numberingOffset = $numberingOffset;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/UuidCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/UuidCaster.php
new file mode 100644
index 0000000..b102774
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/UuidCaster.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Ramsey\Uuid\UuidInterface;
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ */
+final class UuidCaster
+{
+ public static function castRamseyUuid(UuidInterface $c, array $a, Stub $stub, bool $isNested): array
+ {
+ $a += [
+ Caster::PREFIX_VIRTUAL.'uuid' => (string) $c,
+ ];
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php
new file mode 100644
index 0000000..fa0b55d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php
@@ -0,0 +1,79 @@
+<?php
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts XmlReader class to array representation.
+ *
+ * @author Baptiste Clavié <clavie.b@gmail.com>
+ *
+ * @final
+ */
+class XmlReaderCaster
+{
+ private const NODE_TYPES = [
+ \XMLReader::NONE => 'NONE',
+ \XMLReader::ELEMENT => 'ELEMENT',
+ \XMLReader::ATTRIBUTE => 'ATTRIBUTE',
+ \XMLReader::TEXT => 'TEXT',
+ \XMLReader::CDATA => 'CDATA',
+ \XMLReader::ENTITY_REF => 'ENTITY_REF',
+ \XMLReader::ENTITY => 'ENTITY',
+ \XMLReader::PI => 'PI (Processing Instruction)',
+ \XMLReader::COMMENT => 'COMMENT',
+ \XMLReader::DOC => 'DOC',
+ \XMLReader::DOC_TYPE => 'DOC_TYPE',
+ \XMLReader::DOC_FRAGMENT => 'DOC_FRAGMENT',
+ \XMLReader::NOTATION => 'NOTATION',
+ \XMLReader::WHITESPACE => 'WHITESPACE',
+ \XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE',
+ \XMLReader::END_ELEMENT => 'END_ELEMENT',
+ \XMLReader::END_ENTITY => 'END_ENTITY',
+ \XMLReader::XML_DECLARATION => 'XML_DECLARATION',
+ ];
+
+ public static function castXmlReader(\XMLReader $reader, array $a, Stub $stub, bool $isNested)
+ {
+ $props = Caster::PREFIX_VIRTUAL.'parserProperties';
+ $info = [
+ 'localName' => $reader->localName,
+ 'prefix' => $reader->prefix,
+ 'nodeType' => new ConstStub(self::NODE_TYPES[$reader->nodeType], $reader->nodeType),
+ 'depth' => $reader->depth,
+ 'isDefault' => $reader->isDefault,
+ 'isEmptyElement' => \XMLReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement,
+ 'xmlLang' => $reader->xmlLang,
+ 'attributeCount' => $reader->attributeCount,
+ 'value' => $reader->value,
+ 'namespaceURI' => $reader->namespaceURI,
+ 'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI,
+ $props => [
+ 'LOADDTD' => $reader->getParserProperty(\XMLReader::LOADDTD),
+ 'DEFAULTATTRS' => $reader->getParserProperty(\XMLReader::DEFAULTATTRS),
+ 'VALIDATE' => $reader->getParserProperty(\XMLReader::VALIDATE),
+ 'SUBST_ENTITIES' => $reader->getParserProperty(\XMLReader::SUBST_ENTITIES),
+ ],
+ ];
+
+ if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, [], $count)) {
+ $info[$props] = new EnumStub($info[$props]);
+ $info[$props]->cut = $count;
+ }
+
+ $info = Caster::filter($info, Caster::EXCLUDE_EMPTY, [], $count);
+ // +2 because hasValue and hasAttributes are always filtered
+ $stub->cut += $count + 2;
+
+ return $a + $info;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php
new file mode 100644
index 0000000..ba55fce
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * Casts XML resources to array representation.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @final
+ */
+class XmlResourceCaster
+{
+ private const XML_ERRORS = [
+ \XML_ERROR_NONE => 'XML_ERROR_NONE',
+ \XML_ERROR_NO_MEMORY => 'XML_ERROR_NO_MEMORY',
+ \XML_ERROR_SYNTAX => 'XML_ERROR_SYNTAX',
+ \XML_ERROR_NO_ELEMENTS => 'XML_ERROR_NO_ELEMENTS',
+ \XML_ERROR_INVALID_TOKEN => 'XML_ERROR_INVALID_TOKEN',
+ \XML_ERROR_UNCLOSED_TOKEN => 'XML_ERROR_UNCLOSED_TOKEN',
+ \XML_ERROR_PARTIAL_CHAR => 'XML_ERROR_PARTIAL_CHAR',
+ \XML_ERROR_TAG_MISMATCH => 'XML_ERROR_TAG_MISMATCH',
+ \XML_ERROR_DUPLICATE_ATTRIBUTE => 'XML_ERROR_DUPLICATE_ATTRIBUTE',
+ \XML_ERROR_JUNK_AFTER_DOC_ELEMENT => 'XML_ERROR_JUNK_AFTER_DOC_ELEMENT',
+ \XML_ERROR_PARAM_ENTITY_REF => 'XML_ERROR_PARAM_ENTITY_REF',
+ \XML_ERROR_UNDEFINED_ENTITY => 'XML_ERROR_UNDEFINED_ENTITY',
+ \XML_ERROR_RECURSIVE_ENTITY_REF => 'XML_ERROR_RECURSIVE_ENTITY_REF',
+ \XML_ERROR_ASYNC_ENTITY => 'XML_ERROR_ASYNC_ENTITY',
+ \XML_ERROR_BAD_CHAR_REF => 'XML_ERROR_BAD_CHAR_REF',
+ \XML_ERROR_BINARY_ENTITY_REF => 'XML_ERROR_BINARY_ENTITY_REF',
+ \XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => 'XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF',
+ \XML_ERROR_MISPLACED_XML_PI => 'XML_ERROR_MISPLACED_XML_PI',
+ \XML_ERROR_UNKNOWN_ENCODING => 'XML_ERROR_UNKNOWN_ENCODING',
+ \XML_ERROR_INCORRECT_ENCODING => 'XML_ERROR_INCORRECT_ENCODING',
+ \XML_ERROR_UNCLOSED_CDATA_SECTION => 'XML_ERROR_UNCLOSED_CDATA_SECTION',
+ \XML_ERROR_EXTERNAL_ENTITY_HANDLING => 'XML_ERROR_EXTERNAL_ENTITY_HANDLING',
+ ];
+
+ public static function castXml($h, array $a, Stub $stub, bool $isNested)
+ {
+ $a['current_byte_index'] = xml_get_current_byte_index($h);
+ $a['current_column_number'] = xml_get_current_column_number($h);
+ $a['current_line_number'] = xml_get_current_line_number($h);
+ $a['error_code'] = xml_get_error_code($h);
+
+ if (isset(self::XML_ERRORS[$a['error_code']])) {
+ $a['error_code'] = new ConstStub(self::XML_ERRORS[$a['error_code']], $a['error_code']);
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/AbstractCloner.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/AbstractCloner.php
new file mode 100644
index 0000000..ac55da5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/AbstractCloner.php
@@ -0,0 +1,384 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Cloner;
+
+use Symfony\Component\VarDumper\Caster\Caster;
+use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
+
+/**
+ * AbstractCloner implements a generic caster mechanism for objects and resources.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+abstract class AbstractCloner implements ClonerInterface
+{
+ public static $defaultCasters = [
+ '__PHP_Incomplete_Class' => ['Symfony\Component\VarDumper\Caster\Caster', 'castPhpIncompleteClass'],
+
+ 'Symfony\Component\VarDumper\Caster\CutStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'],
+ 'Symfony\Component\VarDumper\Caster\CutArrayStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'],
+ 'Symfony\Component\VarDumper\Caster\ConstStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'],
+ 'Symfony\Component\VarDumper\Caster\EnumStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castEnum'],
+
+ 'Closure' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'],
+ 'Generator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'],
+ 'ReflectionType' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'],
+ 'ReflectionAttribute' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castAttribute'],
+ 'ReflectionGenerator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'],
+ 'ReflectionClass' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'],
+ 'ReflectionClassConstant' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClassConstant'],
+ 'ReflectionFunctionAbstract' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'],
+ 'ReflectionMethod' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'],
+ 'ReflectionParameter' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'],
+ 'ReflectionProperty' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castProperty'],
+ 'ReflectionReference' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReference'],
+ 'ReflectionExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castExtension'],
+ 'ReflectionZendExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castZendExtension'],
+
+ 'Doctrine\Common\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+ 'Doctrine\Common\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castCommonProxy'],
+ 'Doctrine\ORM\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castOrmProxy'],
+ 'Doctrine\ORM\PersistentCollection' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castPersistentCollection'],
+ 'Doctrine\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+
+ 'DOMException' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'],
+ 'DOMStringList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
+ 'DOMNameList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
+ 'DOMImplementation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'],
+ 'DOMImplementationList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
+ 'DOMNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'],
+ 'DOMNameSpaceNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNameSpaceNode'],
+ 'DOMDocument' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocument'],
+ 'DOMNodeList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
+ 'DOMNamedNodeMap' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
+ 'DOMCharacterData' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'],
+ 'DOMAttr' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'],
+ 'DOMElement' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'],
+ 'DOMText' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'],
+ 'DOMTypeinfo' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castTypeinfo'],
+ 'DOMDomError' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDomError'],
+ 'DOMLocator' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLocator'],
+ 'DOMDocumentType' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'],
+ 'DOMNotation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'],
+ 'DOMEntity' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'],
+ 'DOMProcessingInstruction' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'],
+ 'DOMXPath' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castXPath'],
+
+ 'XMLReader' => ['Symfony\Component\VarDumper\Caster\XmlReaderCaster', 'castXmlReader'],
+
+ 'ErrorException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castErrorException'],
+ 'Exception' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castException'],
+ 'Error' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castError'],
+ 'Symfony\Bridge\Monolog\Logger' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+ 'Symfony\Component\DependencyInjection\ContainerInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+ 'Symfony\Component\EventDispatcher\EventDispatcherInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+ 'Symfony\Component\HttpClient\CurlHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'],
+ 'Symfony\Component\HttpClient\NativeHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'],
+ 'Symfony\Component\HttpClient\Response\CurlResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'],
+ 'Symfony\Component\HttpClient\Response\NativeResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'],
+ 'Symfony\Component\HttpFoundation\Request' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castRequest'],
+ 'Symfony\Component\VarDumper\Exception\ThrowingCasterException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castThrowingCasterException'],
+ 'Symfony\Component\VarDumper\Caster\TraceStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castTraceStub'],
+ 'Symfony\Component\VarDumper\Caster\FrameStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFrameStub'],
+ 'Symfony\Component\VarDumper\Cloner\AbstractCloner' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+ 'Symfony\Component\ErrorHandler\Exception\SilencedErrorContext' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castSilencedErrorContext'],
+
+ 'Imagine\Image\ImageInterface' => ['Symfony\Component\VarDumper\Caster\ImagineCaster', 'castImage'],
+
+ 'Ramsey\Uuid\UuidInterface' => ['Symfony\Component\VarDumper\Caster\UuidCaster', 'castRamseyUuid'],
+
+ 'ProxyManager\Proxy\ProxyInterface' => ['Symfony\Component\VarDumper\Caster\ProxyManagerCaster', 'castProxy'],
+ 'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+ 'PHPUnit\Framework\MockObject\MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+ 'PHPUnit\Framework\MockObject\Stub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+ 'Prophecy\Prophecy\ProphecySubjectInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+ 'Mockery\MockInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
+
+ 'PDO' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdo'],
+ 'PDOStatement' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdoStatement'],
+
+ 'AMQPConnection' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castConnection'],
+ 'AMQPChannel' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castChannel'],
+ 'AMQPQueue' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castQueue'],
+ 'AMQPExchange' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castExchange'],
+ 'AMQPEnvelope' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'],
+
+ 'ArrayObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'],
+ 'ArrayIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayIterator'],
+ 'SplDoublyLinkedList' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'],
+ 'SplFileInfo' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'],
+ 'SplFileObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'],
+ 'SplHeap' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'],
+ 'SplObjectStorage' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'],
+ 'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'],
+ 'OuterIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castOuterIterator'],
+ 'WeakReference' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castWeakReference'],
+
+ 'Redis' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'],
+ 'RedisArray' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'],
+ 'RedisCluster' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisCluster'],
+
+ 'DateTimeInterface' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'],
+ 'DateInterval' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'],
+ 'DateTimeZone' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castTimeZone'],
+ 'DatePeriod' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castPeriod'],
+
+ 'GMP' => ['Symfony\Component\VarDumper\Caster\GmpCaster', 'castGmp'],
+
+ 'MessageFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castMessageFormatter'],
+ 'NumberFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castNumberFormatter'],
+ 'IntlTimeZone' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlTimeZone'],
+ 'IntlCalendar' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlCalendar'],
+ 'IntlDateFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlDateFormatter'],
+
+ 'Memcached' => ['Symfony\Component\VarDumper\Caster\MemcachedCaster', 'castMemcached'],
+
+ 'Ds\Collection' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castCollection'],
+ 'Ds\Map' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castMap'],
+ 'Ds\Pair' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPair'],
+ 'Symfony\Component\VarDumper\Caster\DsPairStub' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPairStub'],
+
+ 'CurlHandle' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'],
+ ':curl' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'],
+
+ ':dba' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'],
+ ':dba persistent' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'],
+
+ 'GdImage' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'],
+ ':gd' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'],
+
+ ':mysql link' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castMysqlLink'],
+ ':pgsql large object' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLargeObject'],
+ ':pgsql link' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'],
+ ':pgsql link persistent' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'],
+ ':pgsql result' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castResult'],
+ ':process' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castProcess'],
+ ':stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'],
+
+ 'OpenSSLCertificate' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'],
+ ':OpenSSL X.509' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'],
+
+ ':persistent stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'],
+ ':stream-context' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStreamContext'],
+
+ 'XmlParser' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'],
+ ':xml' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'],
+
+ 'RdKafka' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castRdKafka'],
+ 'RdKafka\Conf' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castConf'],
+ 'RdKafka\KafkaConsumer' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castKafkaConsumer'],
+ 'RdKafka\Metadata\Broker' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castBrokerMetadata'],
+ 'RdKafka\Metadata\Collection' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castCollectionMetadata'],
+ 'RdKafka\Metadata\Partition' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castPartitionMetadata'],
+ 'RdKafka\Metadata\Topic' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicMetadata'],
+ 'RdKafka\Message' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castMessage'],
+ 'RdKafka\Topic' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopic'],
+ 'RdKafka\TopicPartition' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicPartition'],
+ 'RdKafka\TopicConf' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicConf'],
+ ];
+
+ protected $maxItems = 2500;
+ protected $maxString = -1;
+ protected $minDepth = 1;
+
+ private $casters = [];
+ private $prevErrorHandler;
+ private $classInfo = [];
+ private $filter = 0;
+
+ /**
+ * @param callable[]|null $casters A map of casters
+ *
+ * @see addCasters
+ */
+ public function __construct(array $casters = null)
+ {
+ if (null === $casters) {
+ $casters = static::$defaultCasters;
+ }
+ $this->addCasters($casters);
+ }
+
+ /**
+ * Adds casters for resources and objects.
+ *
+ * Maps resources or objects types to a callback.
+ * Types are in the key, with a callable caster for value.
+ * Resource types are to be prefixed with a `:`,
+ * see e.g. static::$defaultCasters.
+ *
+ * @param callable[] $casters A map of casters
+ */
+ public function addCasters(array $casters)
+ {
+ foreach ($casters as $type => $callback) {
+ $this->casters[$type][] = $callback;
+ }
+ }
+
+ /**
+ * Sets the maximum number of items to clone past the minimum depth in nested structures.
+ */
+ public function setMaxItems(int $maxItems)
+ {
+ $this->maxItems = $maxItems;
+ }
+
+ /**
+ * Sets the maximum cloned length for strings.
+ */
+ public function setMaxString(int $maxString)
+ {
+ $this->maxString = $maxString;
+ }
+
+ /**
+ * Sets the minimum tree depth where we are guaranteed to clone all the items. After this
+ * depth is reached, only setMaxItems items will be cloned.
+ */
+ public function setMinDepth(int $minDepth)
+ {
+ $this->minDepth = $minDepth;
+ }
+
+ /**
+ * Clones a PHP variable.
+ *
+ * @param mixed $var Any PHP variable
+ * @param int $filter A bit field of Caster::EXCLUDE_* constants
+ *
+ * @return Data The cloned variable represented by a Data object
+ */
+ public function cloneVar($var, int $filter = 0)
+ {
+ $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) {
+ if (\E_RECOVERABLE_ERROR === $type || \E_USER_ERROR === $type) {
+ // Cloner never dies
+ throw new \ErrorException($msg, 0, $type, $file, $line);
+ }
+
+ if ($this->prevErrorHandler) {
+ return ($this->prevErrorHandler)($type, $msg, $file, $line, $context);
+ }
+
+ return false;
+ });
+ $this->filter = $filter;
+
+ if ($gc = gc_enabled()) {
+ gc_disable();
+ }
+ try {
+ return new Data($this->doClone($var));
+ } finally {
+ if ($gc) {
+ gc_enable();
+ }
+ restore_error_handler();
+ $this->prevErrorHandler = null;
+ }
+ }
+
+ /**
+ * Effectively clones the PHP variable.
+ *
+ * @param mixed $var Any PHP variable
+ *
+ * @return array The cloned variable represented in an array
+ */
+ abstract protected function doClone($var);
+
+ /**
+ * Casts an object to an array representation.
+ *
+ * @param bool $isNested True if the object is nested in the dumped structure
+ *
+ * @return array The object casted as array
+ */
+ protected function castObject(Stub $stub, bool $isNested)
+ {
+ $obj = $stub->value;
+ $class = $stub->class;
+
+ if (\PHP_VERSION_ID < 80000 ? "\0" === ($class[15] ?? null) : str_contains($class, "@anonymous\0")) {
+ $stub->class = get_debug_type($obj);
+ }
+ if (isset($this->classInfo[$class])) {
+ [$i, $parents, $hasDebugInfo, $fileInfo] = $this->classInfo[$class];
+ } else {
+ $i = 2;
+ $parents = [$class];
+ $hasDebugInfo = method_exists($class, '__debugInfo');
+
+ foreach (class_parents($class) as $p) {
+ $parents[] = $p;
+ ++$i;
+ }
+ foreach (class_implements($class) as $p) {
+ $parents[] = $p;
+ ++$i;
+ }
+ $parents[] = '*';
+
+ $r = new \ReflectionClass($class);
+ $fileInfo = $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : [
+ 'file' => $r->getFileName(),
+ 'line' => $r->getStartLine(),
+ ];
+
+ $this->classInfo[$class] = [$i, $parents, $hasDebugInfo, $fileInfo];
+ }
+
+ $stub->attr += $fileInfo;
+ $a = Caster::castObject($obj, $class, $hasDebugInfo, $stub->class);
+
+ try {
+ while ($i--) {
+ if (!empty($this->casters[$p = $parents[$i]])) {
+ foreach ($this->casters[$p] as $callback) {
+ $a = $callback($obj, $a, $stub, $isNested, $this->filter);
+ }
+ }
+ }
+ } catch (\Exception $e) {
+ $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a;
+ }
+
+ return $a;
+ }
+
+ /**
+ * Casts a resource to an array representation.
+ *
+ * @param bool $isNested True if the object is nested in the dumped structure
+ *
+ * @return array The resource casted as array
+ */
+ protected function castResource(Stub $stub, bool $isNested)
+ {
+ $a = [];
+ $res = $stub->value;
+ $type = $stub->class;
+
+ try {
+ if (!empty($this->casters[':'.$type])) {
+ foreach ($this->casters[':'.$type] as $callback) {
+ $a = $callback($res, $a, $stub, $isNested, $this->filter);
+ }
+ }
+ } catch (\Exception $e) {
+ $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a;
+ }
+
+ return $a;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/ClonerInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/ClonerInterface.php
new file mode 100644
index 0000000..7ed287a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/ClonerInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Cloner;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+interface ClonerInterface
+{
+ /**
+ * Clones a PHP variable.
+ *
+ * @param mixed $var Any PHP variable
+ *
+ * @return Data The cloned variable represented by a Data object
+ */
+ public function cloneVar($var);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Cursor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Cursor.php
new file mode 100644
index 0000000..1fd796d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Cursor.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Cloner;
+
+/**
+ * Represents the current state of a dumper while dumping.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class Cursor
+{
+ public const HASH_INDEXED = Stub::ARRAY_INDEXED;
+ public const HASH_ASSOC = Stub::ARRAY_ASSOC;
+ public const HASH_OBJECT = Stub::TYPE_OBJECT;
+ public const HASH_RESOURCE = Stub::TYPE_RESOURCE;
+
+ public $depth = 0;
+ public $refIndex = 0;
+ public $softRefTo = 0;
+ public $softRefCount = 0;
+ public $softRefHandle = 0;
+ public $hardRefTo = 0;
+ public $hardRefCount = 0;
+ public $hardRefHandle = 0;
+ public $hashType;
+ public $hashKey;
+ public $hashKeyIsBinary;
+ public $hashIndex = 0;
+ public $hashLength = 0;
+ public $hashCut = 0;
+ public $stop = false;
+ public $attr = [];
+ public $skipChildren = false;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Data.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Data.php
new file mode 100644
index 0000000..c868862
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Data.php
@@ -0,0 +1,460 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Cloner;
+
+use Symfony\Component\VarDumper\Caster\Caster;
+use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class Data implements \ArrayAccess, \Countable, \IteratorAggregate
+{
+ private $data;
+ private $position = 0;
+ private $key = 0;
+ private $maxDepth = 20;
+ private $maxItemsPerDepth = -1;
+ private $useRefHandles = -1;
+ private $context = [];
+
+ /**
+ * @param array $data An array as returned by ClonerInterface::cloneVar()
+ */
+ public function __construct(array $data)
+ {
+ $this->data = $data;
+ }
+
+ /**
+ * @return string|null The type of the value
+ */
+ public function getType()
+ {
+ $item = $this->data[$this->position][$this->key];
+
+ if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
+ $item = $item->value;
+ }
+ if (!$item instanceof Stub) {
+ return \gettype($item);
+ }
+ if (Stub::TYPE_STRING === $item->type) {
+ return 'string';
+ }
+ if (Stub::TYPE_ARRAY === $item->type) {
+ return 'array';
+ }
+ if (Stub::TYPE_OBJECT === $item->type) {
+ return $item->class;
+ }
+ if (Stub::TYPE_RESOURCE === $item->type) {
+ return $item->class.' resource';
+ }
+
+ return null;
+ }
+
+ /**
+ * @param array|bool $recursive Whether values should be resolved recursively or not
+ *
+ * @return string|int|float|bool|array|Data[]|null A native representation of the original value
+ */
+ public function getValue($recursive = false)
+ {
+ $item = $this->data[$this->position][$this->key];
+
+ if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
+ $item = $item->value;
+ }
+ if (!($item = $this->getStub($item)) instanceof Stub) {
+ return $item;
+ }
+ if (Stub::TYPE_STRING === $item->type) {
+ return $item->value;
+ }
+
+ $children = $item->position ? $this->data[$item->position] : [];
+
+ foreach ($children as $k => $v) {
+ if ($recursive && !($v = $this->getStub($v)) instanceof Stub) {
+ continue;
+ }
+ $children[$k] = clone $this;
+ $children[$k]->key = $k;
+ $children[$k]->position = $item->position;
+
+ if ($recursive) {
+ if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) {
+ $recursive = (array) $recursive;
+ if (isset($recursive[$v->position])) {
+ continue;
+ }
+ $recursive[$v->position] = true;
+ }
+ $children[$k] = $children[$k]->getValue($recursive);
+ }
+ }
+
+ return $children;
+ }
+
+ /**
+ * @return int
+ */
+ public function count()
+ {
+ return \count($this->getValue());
+ }
+
+ /**
+ * @return \Traversable
+ */
+ public function getIterator()
+ {
+ if (!\is_array($value = $this->getValue())) {
+ throw new \LogicException(sprintf('"%s" object holds non-iterable type "%s".', self::class, get_debug_type($value)));
+ }
+
+ yield from $value;
+ }
+
+ public function __get(string $key)
+ {
+ if (null !== $data = $this->seek($key)) {
+ $item = $this->getStub($data->data[$data->position][$data->key]);
+
+ return $item instanceof Stub || [] === $item ? $data : $item;
+ }
+
+ return null;
+ }
+
+ /**
+ * @return bool
+ */
+ public function __isset(string $key)
+ {
+ return null !== $this->seek($key);
+ }
+
+ /**
+ * @return bool
+ */
+ public function offsetExists($key)
+ {
+ return $this->__isset($key);
+ }
+
+ /**
+ * @return mixed
+ */
+ public function offsetGet($key)
+ {
+ return $this->__get($key);
+ }
+
+ /**
+ * @return void
+ */
+ public function offsetSet($key, $value)
+ {
+ throw new \BadMethodCallException(self::class.' objects are immutable.');
+ }
+
+ /**
+ * @return void
+ */
+ public function offsetUnset($key)
+ {
+ throw new \BadMethodCallException(self::class.' objects are immutable.');
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ $value = $this->getValue();
+
+ if (!\is_array($value)) {
+ return (string) $value;
+ }
+
+ return sprintf('%s (count=%d)', $this->getType(), \count($value));
+ }
+
+ /**
+ * Returns a depth limited clone of $this.
+ *
+ * @return static
+ */
+ public function withMaxDepth(int $maxDepth)
+ {
+ $data = clone $this;
+ $data->maxDepth = (int) $maxDepth;
+
+ return $data;
+ }
+
+ /**
+ * Limits the number of elements per depth level.
+ *
+ * @return static
+ */
+ public function withMaxItemsPerDepth(int $maxItemsPerDepth)
+ {
+ $data = clone $this;
+ $data->maxItemsPerDepth = (int) $maxItemsPerDepth;
+
+ return $data;
+ }
+
+ /**
+ * Enables/disables objects' identifiers tracking.
+ *
+ * @param bool $useRefHandles False to hide global ref. handles
+ *
+ * @return static
+ */
+ public function withRefHandles(bool $useRefHandles)
+ {
+ $data = clone $this;
+ $data->useRefHandles = $useRefHandles ? -1 : 0;
+
+ return $data;
+ }
+
+ /**
+ * @return static
+ */
+ public function withContext(array $context)
+ {
+ $data = clone $this;
+ $data->context = $context;
+
+ return $data;
+ }
+
+ /**
+ * Seeks to a specific key in nested data structures.
+ *
+ * @param string|int $key The key to seek to
+ *
+ * @return static|null Null if the key is not set
+ */
+ public function seek($key)
+ {
+ $item = $this->data[$this->position][$this->key];
+
+ if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) {
+ $item = $item->value;
+ }
+ if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) {
+ return null;
+ }
+ $keys = [$key];
+
+ switch ($item->type) {
+ case Stub::TYPE_OBJECT:
+ $keys[] = Caster::PREFIX_DYNAMIC.$key;
+ $keys[] = Caster::PREFIX_PROTECTED.$key;
+ $keys[] = Caster::PREFIX_VIRTUAL.$key;
+ $keys[] = "\0$item->class\0$key";
+ // no break
+ case Stub::TYPE_ARRAY:
+ case Stub::TYPE_RESOURCE:
+ break;
+ default:
+ return null;
+ }
+
+ $data = null;
+ $children = $this->data[$item->position];
+
+ foreach ($keys as $key) {
+ if (isset($children[$key]) || \array_key_exists($key, $children)) {
+ $data = clone $this;
+ $data->key = $key;
+ $data->position = $item->position;
+ break;
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Dumps data with a DumperInterface dumper.
+ */
+ public function dump(DumperInterface $dumper)
+ {
+ $refs = [0];
+ $cursor = new Cursor();
+
+ if ($cursor->attr = $this->context[SourceContextProvider::class] ?? []) {
+ $cursor->attr['if_links'] = true;
+ $cursor->hashType = -1;
+ $dumper->dumpScalar($cursor, 'default', '^');
+ $cursor->attr = ['if_links' => true];
+ $dumper->dumpScalar($cursor, 'default', ' ');
+ $cursor->hashType = 0;
+ }
+
+ $this->dumpItem($dumper, $cursor, $refs, $this->data[$this->position][$this->key]);
+ }
+
+ /**
+ * Depth-first dumping of items.
+ *
+ * @param mixed $item A Stub object or the original value being dumped
+ */
+ private function dumpItem(DumperInterface $dumper, Cursor $cursor, array &$refs, $item)
+ {
+ $cursor->refIndex = 0;
+ $cursor->softRefTo = $cursor->softRefHandle = $cursor->softRefCount = 0;
+ $cursor->hardRefTo = $cursor->hardRefHandle = $cursor->hardRefCount = 0;
+ $firstSeen = true;
+
+ if (!$item instanceof Stub) {
+ $cursor->attr = [];
+ $type = \gettype($item);
+ if ($item && 'array' === $type) {
+ $item = $this->getStub($item);
+ }
+ } elseif (Stub::TYPE_REF === $item->type) {
+ if ($item->handle) {
+ if (!isset($refs[$r = $item->handle - (\PHP_INT_MAX >> 1)])) {
+ $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0];
+ } else {
+ $firstSeen = false;
+ }
+ $cursor->hardRefTo = $refs[$r];
+ $cursor->hardRefHandle = $this->useRefHandles & $item->handle;
+ $cursor->hardRefCount = 0 < $item->handle ? $item->refCount : 0;
+ }
+ $cursor->attr = $item->attr;
+ $type = $item->class ?: \gettype($item->value);
+ $item = $this->getStub($item->value);
+ }
+ if ($item instanceof Stub) {
+ if ($item->refCount) {
+ if (!isset($refs[$r = $item->handle])) {
+ $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0];
+ } else {
+ $firstSeen = false;
+ }
+ $cursor->softRefTo = $refs[$r];
+ }
+ $cursor->softRefHandle = $this->useRefHandles & $item->handle;
+ $cursor->softRefCount = $item->refCount;
+ $cursor->attr = $item->attr;
+ $cut = $item->cut;
+
+ if ($item->position && $firstSeen) {
+ $children = $this->data[$item->position];
+
+ if ($cursor->stop) {
+ if ($cut >= 0) {
+ $cut += \count($children);
+ }
+ $children = [];
+ }
+ } else {
+ $children = [];
+ }
+ switch ($item->type) {
+ case Stub::TYPE_STRING:
+ $dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut);
+ break;
+
+ case Stub::TYPE_ARRAY:
+ $item = clone $item;
+ $item->type = $item->class;
+ $item->class = $item->value;
+ // no break
+ case Stub::TYPE_OBJECT:
+ case Stub::TYPE_RESOURCE:
+ $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth;
+ $dumper->enterHash($cursor, $item->type, $item->class, $withChildren);
+ if ($withChildren) {
+ if ($cursor->skipChildren) {
+ $withChildren = false;
+ $cut = -1;
+ } else {
+ $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class);
+ }
+ } elseif ($children && 0 <= $cut) {
+ $cut += \count($children);
+ }
+ $cursor->skipChildren = false;
+ $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut);
+ break;
+
+ default:
+ throw new \RuntimeException(sprintf('Unexpected Stub type: "%s".', $item->type));
+ }
+ } elseif ('array' === $type) {
+ $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false);
+ $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, false, 0);
+ } elseif ('string' === $type) {
+ $dumper->dumpString($cursor, $item, false, 0);
+ } else {
+ $dumper->dumpScalar($cursor, $type, $item);
+ }
+ }
+
+ /**
+ * Dumps children of hash structures.
+ *
+ * @return int The final number of removed items
+ */
+ private function dumpChildren(DumperInterface $dumper, Cursor $parentCursor, array &$refs, array $children, int $hashCut, int $hashType, bool $dumpKeys): int
+ {
+ $cursor = clone $parentCursor;
+ ++$cursor->depth;
+ $cursor->hashType = $hashType;
+ $cursor->hashIndex = 0;
+ $cursor->hashLength = \count($children);
+ $cursor->hashCut = $hashCut;
+ foreach ($children as $key => $child) {
+ $cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);
+ $cursor->hashKey = $dumpKeys ? $key : null;
+ $this->dumpItem($dumper, $cursor, $refs, $child);
+ if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {
+ $parentCursor->stop = true;
+
+ return $hashCut >= 0 ? $hashCut + $cursor->hashLength - $cursor->hashIndex : $hashCut;
+ }
+ }
+
+ return $hashCut;
+ }
+
+ private function getStub($item)
+ {
+ if (!$item || !\is_array($item)) {
+ return $item;
+ }
+
+ $stub = new Stub();
+ $stub->type = Stub::TYPE_ARRAY;
+ foreach ($item as $stub->class => $stub->position) {
+ }
+ if (isset($item[0])) {
+ $stub->cut = $item[0];
+ }
+ $stub->value = $stub->cut + ($stub->position ? \count($this->data[$stub->position]) : 0);
+
+ return $stub;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/DumperInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/DumperInterface.php
new file mode 100644
index 0000000..6d60b72
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/DumperInterface.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Cloner;
+
+/**
+ * DumperInterface used by Data objects.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+interface DumperInterface
+{
+ /**
+ * Dumps a scalar value.
+ *
+ * @param string $type The PHP type of the value being dumped
+ * @param string|int|float|bool $value The scalar value being dumped
+ */
+ public function dumpScalar(Cursor $cursor, string $type, $value);
+
+ /**
+ * Dumps a string.
+ *
+ * @param string $str The string being dumped
+ * @param bool $bin Whether $str is UTF-8 or binary encoded
+ * @param int $cut The number of characters $str has been cut by
+ */
+ public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut);
+
+ /**
+ * Dumps while entering an hash.
+ *
+ * @param int $type A Cursor::HASH_* const for the type of hash
+ * @param string|int $class The object class, resource type or array count
+ * @param bool $hasChild When the dump of the hash has child item
+ */
+ public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild);
+
+ /**
+ * Dumps while leaving an hash.
+ *
+ * @param int $type A Cursor::HASH_* const for the type of hash
+ * @param string|int $class The object class, resource type or array count
+ * @param bool $hasChild When the dump of the hash has child item
+ * @param int $cut The number of items the hash has been cut by
+ */
+ public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Stub.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Stub.php
new file mode 100644
index 0000000..073c56e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Stub.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Cloner;
+
+/**
+ * Represents the main properties of a PHP variable.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class Stub
+{
+ public const TYPE_REF = 1;
+ public const TYPE_STRING = 2;
+ public const TYPE_ARRAY = 3;
+ public const TYPE_OBJECT = 4;
+ public const TYPE_RESOURCE = 5;
+
+ public const STRING_BINARY = 1;
+ public const STRING_UTF8 = 2;
+
+ public const ARRAY_ASSOC = 1;
+ public const ARRAY_INDEXED = 2;
+
+ public $type = self::TYPE_REF;
+ public $class = '';
+ public $value;
+ public $cut = 0;
+ public $handle = 0;
+ public $refCount = 0;
+ public $position = 0;
+ public $attr = [];
+
+ private static $defaultProperties = [];
+
+ /**
+ * @internal
+ */
+ public function __sleep(): array
+ {
+ $properties = [];
+
+ if (!isset(self::$defaultProperties[$c = static::class])) {
+ self::$defaultProperties[$c] = get_class_vars($c);
+
+ foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) {
+ unset(self::$defaultProperties[$c][$k]);
+ }
+ }
+
+ foreach (self::$defaultProperties[$c] as $k => $v) {
+ if ($this->$k !== $v) {
+ $properties[] = $k;
+ }
+ }
+
+ return $properties;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/VarCloner.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/VarCloner.php
new file mode 100644
index 0000000..90d5ac9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/VarCloner.php
@@ -0,0 +1,288 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Cloner;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class VarCloner extends AbstractCloner
+{
+ private static $gid;
+ private static $arrayCache = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClone($var)
+ {
+ $len = 1; // Length of $queue
+ $pos = 0; // Number of cloned items past the minimum depth
+ $refsCounter = 0; // Hard references counter
+ $queue = [[$var]]; // This breadth-first queue is the return value
+ $hardRefs = []; // Map of original zval ids to stub objects
+ $objRefs = []; // Map of original object handles to their stub object counterpart
+ $objects = []; // Keep a ref to objects to ensure their handle cannot be reused while cloning
+ $resRefs = []; // Map of original resource handles to their stub object counterpart
+ $values = []; // Map of stub objects' ids to original values
+ $maxItems = $this->maxItems;
+ $maxString = $this->maxString;
+ $minDepth = $this->minDepth;
+ $currentDepth = 0; // Current tree depth
+ $currentDepthFinalIndex = 0; // Final $queue index for current tree depth
+ $minimumDepthReached = 0 === $minDepth; // Becomes true when minimum tree depth has been reached
+ $cookie = (object) []; // Unique object used to detect hard references
+ $a = null; // Array cast for nested structures
+ $stub = null; // Stub capturing the main properties of an original item value
+ // or null if the original value is used directly
+
+ if (!$gid = self::$gid) {
+ $gid = self::$gid = md5(random_bytes(6)); // Unique string used to detect the special $GLOBALS variable
+ }
+ $arrayStub = new Stub();
+ $arrayStub->type = Stub::TYPE_ARRAY;
+ $fromObjCast = false;
+
+ for ($i = 0; $i < $len; ++$i) {
+ // Detect when we move on to the next tree depth
+ if ($i > $currentDepthFinalIndex) {
+ ++$currentDepth;
+ $currentDepthFinalIndex = $len - 1;
+ if ($currentDepth >= $minDepth) {
+ $minimumDepthReached = true;
+ }
+ }
+
+ $refs = $vals = $queue[$i];
+ foreach ($vals as $k => $v) {
+ // $v is the original value or a stub object in case of hard references
+
+ if (\PHP_VERSION_ID >= 70400) {
+ $zvalIsRef = null !== \ReflectionReference::fromArrayElement($vals, $k);
+ } else {
+ $refs[$k] = $cookie;
+ $zvalIsRef = $vals[$k] === $cookie;
+ }
+
+ if ($zvalIsRef) {
+ $vals[$k] = &$stub; // Break hard references to make $queue completely
+ unset($stub); // independent from the original structure
+ if ($v instanceof Stub && isset($hardRefs[spl_object_id($v)])) {
+ $vals[$k] = $refs[$k] = $v;
+ if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
+ ++$v->value->refCount;
+ }
+ ++$v->refCount;
+ continue;
+ }
+ $refs[$k] = $vals[$k] = new Stub();
+ $refs[$k]->value = $v;
+ $h = spl_object_id($refs[$k]);
+ $hardRefs[$h] = &$refs[$k];
+ $values[$h] = $v;
+ $vals[$k]->handle = ++$refsCounter;
+ }
+ // Create $stub when the original value $v can not be used directly
+ // If $v is a nested structure, put that structure in array $a
+ switch (true) {
+ case null === $v:
+ case \is_bool($v):
+ case \is_int($v):
+ case \is_float($v):
+ continue 2;
+ case \is_string($v):
+ if ('' === $v) {
+ continue 2;
+ }
+ if (!preg_match('//u', $v)) {
+ $stub = new Stub();
+ $stub->type = Stub::TYPE_STRING;
+ $stub->class = Stub::STRING_BINARY;
+ if (0 <= $maxString && 0 < $cut = \strlen($v) - $maxString) {
+ $stub->cut = $cut;
+ $stub->value = substr($v, 0, -$cut);
+ } else {
+ $stub->value = $v;
+ }
+ } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) {
+ $stub = new Stub();
+ $stub->type = Stub::TYPE_STRING;
+ $stub->class = Stub::STRING_UTF8;
+ $stub->cut = $cut;
+ $stub->value = mb_substr($v, 0, $maxString, 'UTF-8');
+ } else {
+ continue 2;
+ }
+ $a = null;
+ break;
+
+ case \is_array($v):
+ if (!$v) {
+ continue 2;
+ }
+ $stub = $arrayStub;
+ $stub->class = Stub::ARRAY_INDEXED;
+
+ $j = -1;
+ foreach ($v as $gk => $gv) {
+ if ($gk !== ++$j) {
+ $stub->class = Stub::ARRAY_ASSOC;
+ break;
+ }
+ }
+ $a = $v;
+
+ if (Stub::ARRAY_ASSOC === $stub->class) {
+ // Copies of $GLOBALS have very strange behavior,
+ // let's detect them with some black magic
+ if (\PHP_VERSION_ID < 80100 && ($a[$gid] = true) && isset($v[$gid])) {
+ unset($v[$gid]);
+ $a = [];
+ foreach ($v as $gk => &$gv) {
+ if ($v === $gv) {
+ unset($v);
+ $v = new Stub();
+ $v->value = [$v->cut = \count($gv), Stub::TYPE_ARRAY => 0];
+ $v->handle = -1;
+ $gv = &$hardRefs[spl_object_id($v)];
+ $gv = $v;
+ }
+
+ $a[$gk] = &$gv;
+ }
+ unset($gv);
+ } else {
+ $a = $v;
+ }
+ }
+ break;
+
+ case \is_object($v):
+ if (empty($objRefs[$h = spl_object_id($v)])) {
+ $stub = new Stub();
+ $stub->type = Stub::TYPE_OBJECT;
+ $stub->class = \get_class($v);
+ $stub->value = $v;
+ $stub->handle = $h;
+ $a = $this->castObject($stub, 0 < $i);
+ if ($v !== $stub->value) {
+ if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) {
+ break;
+ }
+ $stub->handle = $h = spl_object_id($stub->value);
+ }
+ $stub->value = null;
+ if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
+ $stub->cut = \count($a);
+ $a = null;
+ }
+ }
+ if (empty($objRefs[$h])) {
+ $objRefs[$h] = $stub;
+ $objects[] = $v;
+ } else {
+ $stub = $objRefs[$h];
+ ++$stub->refCount;
+ $a = null;
+ }
+ break;
+
+ default: // resource
+ if (empty($resRefs[$h = (int) $v])) {
+ $stub = new Stub();
+ $stub->type = Stub::TYPE_RESOURCE;
+ if ('Unknown' === $stub->class = @get_resource_type($v)) {
+ $stub->class = 'Closed';
+ }
+ $stub->value = $v;
+ $stub->handle = $h;
+ $a = $this->castResource($stub, 0 < $i);
+ $stub->value = null;
+ if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
+ $stub->cut = \count($a);
+ $a = null;
+ }
+ }
+ if (empty($resRefs[$h])) {
+ $resRefs[$h] = $stub;
+ } else {
+ $stub = $resRefs[$h];
+ ++$stub->refCount;
+ $a = null;
+ }
+ break;
+ }
+
+ if ($a) {
+ if (!$minimumDepthReached || 0 > $maxItems) {
+ $queue[$len] = $a;
+ $stub->position = $len++;
+ } elseif ($pos < $maxItems) {
+ if ($maxItems < $pos += \count($a)) {
+ $a = \array_slice($a, 0, $maxItems - $pos, true);
+ if ($stub->cut >= 0) {
+ $stub->cut += $pos - $maxItems;
+ }
+ }
+ $queue[$len] = $a;
+ $stub->position = $len++;
+ } elseif ($stub->cut >= 0) {
+ $stub->cut += \count($a);
+ $stub->position = 0;
+ }
+ }
+
+ if ($arrayStub === $stub) {
+ if ($arrayStub->cut) {
+ $stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position];
+ $arrayStub->cut = 0;
+ } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) {
+ $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position];
+ } else {
+ self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position];
+ }
+ }
+
+ if ($zvalIsRef) {
+ $refs[$k]->value = $stub;
+ } else {
+ $vals[$k] = $stub;
+ }
+ }
+
+ if ($fromObjCast) {
+ $fromObjCast = false;
+ $refs = $vals;
+ $vals = [];
+ $j = -1;
+ foreach ($queue[$i] as $k => $v) {
+ foreach ([$k => true] as $gk => $gv) {
+ }
+ if ($gk !== $k) {
+ $vals = (object) $vals;
+ $vals->{$k} = $refs[++$j];
+ $vals = (array) $vals;
+ } else {
+ $vals[$k] = $refs[++$j];
+ }
+ }
+ }
+
+ $queue[$i] = $vals;
+ }
+
+ foreach ($values as $h => $v) {
+ $hardRefs[$h] = $v;
+ }
+
+ return $queue;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php
new file mode 100644
index 0000000..7d9ec0e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php
@@ -0,0 +1,88 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Command\Descriptor;
+
+use Symfony\Component\Console\Formatter\OutputFormatterStyle;
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Dumper\CliDumper;
+
+/**
+ * Describe collected data clones for cli output.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ *
+ * @final
+ */
+class CliDescriptor implements DumpDescriptorInterface
+{
+ private $dumper;
+ private $lastIdentifier;
+ private $supportsHref;
+
+ public function __construct(CliDumper $dumper)
+ {
+ $this->dumper = $dumper;
+ $this->supportsHref = method_exists(OutputFormatterStyle::class, 'setHref');
+ }
+
+ public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void
+ {
+ $io = $output instanceof SymfonyStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output);
+ $this->dumper->setColors($output->isDecorated());
+
+ $rows = [['date', date('r', (int) $context['timestamp'])]];
+ $lastIdentifier = $this->lastIdentifier;
+ $this->lastIdentifier = $clientId;
+
+ $section = "Received from client #$clientId";
+ if (isset($context['request'])) {
+ $request = $context['request'];
+ $this->lastIdentifier = $request['identifier'];
+ $section = sprintf('%s %s', $request['method'], $request['uri']);
+ if ($controller = $request['controller']) {
+ $rows[] = ['controller', rtrim($this->dumper->dump($controller, true), "\n")];
+ }
+ } elseif (isset($context['cli'])) {
+ $this->lastIdentifier = $context['cli']['identifier'];
+ $section = '$ '.$context['cli']['command_line'];
+ }
+
+ if ($this->lastIdentifier !== $lastIdentifier) {
+ $io->section($section);
+ }
+
+ if (isset($context['source'])) {
+ $source = $context['source'];
+ $sourceInfo = sprintf('%s on line %d', $source['name'], $source['line']);
+ $fileLink = $source['file_link'] ?? null;
+ if ($this->supportsHref && $fileLink) {
+ $sourceInfo = sprintf('<href=%s>%s</>', $fileLink, $sourceInfo);
+ }
+ $rows[] = ['source', $sourceInfo];
+ $file = $source['file_relative'] ?? $source['file'];
+ $rows[] = ['file', $file];
+ }
+
+ $io->table([], $rows);
+
+ if (!$this->supportsHref && isset($fileLink)) {
+ $io->writeln(['<info>Open source in your IDE/browser:</info>', $fileLink]);
+ $io->newLine();
+ }
+
+ $this->dumper->dump($data);
+ $io->newLine();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php
new file mode 100644
index 0000000..267d27b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Command\Descriptor;
+
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\VarDumper\Cloner\Data;
+
+/**
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+interface DumpDescriptorInterface
+{
+ public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php
new file mode 100644
index 0000000..636b618
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php
@@ -0,0 +1,119 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Command\Descriptor;
+
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Dumper\HtmlDumper;
+
+/**
+ * Describe collected data clones for html output.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ *
+ * @final
+ */
+class HtmlDescriptor implements DumpDescriptorInterface
+{
+ private $dumper;
+ private $initialized = false;
+
+ public function __construct(HtmlDumper $dumper)
+ {
+ $this->dumper = $dumper;
+ }
+
+ public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void
+ {
+ if (!$this->initialized) {
+ $styles = file_get_contents(__DIR__.'/../../Resources/css/htmlDescriptor.css');
+ $scripts = file_get_contents(__DIR__.'/../../Resources/js/htmlDescriptor.js');
+ $output->writeln("<style>$styles</style><script>$scripts</script>");
+ $this->initialized = true;
+ }
+
+ $title = '-';
+ if (isset($context['request'])) {
+ $request = $context['request'];
+ $controller = "<span class='dumped-tag'>{$this->dumper->dump($request['controller'], true, ['maxDepth' => 0])}</span>";
+ $title = sprintf('<code>%s</code> <a href="%s">%s</a>', $request['method'], $uri = $request['uri'], $uri);
+ $dedupIdentifier = $request['identifier'];
+ } elseif (isset($context['cli'])) {
+ $title = '<code>$ </code>'.$context['cli']['command_line'];
+ $dedupIdentifier = $context['cli']['identifier'];
+ } else {
+ $dedupIdentifier = uniqid('', true);
+ }
+
+ $sourceDescription = '';
+ if (isset($context['source'])) {
+ $source = $context['source'];
+ $projectDir = $source['project_dir'] ?? null;
+ $sourceDescription = sprintf('%s on line %d', $source['name'], $source['line']);
+ if (isset($source['file_link'])) {
+ $sourceDescription = sprintf('<a href="%s">%s</a>', $source['file_link'], $sourceDescription);
+ }
+ }
+
+ $isoDate = $this->extractDate($context, 'c');
+ $tags = array_filter([
+ 'controller' => $controller ?? null,
+ 'project dir' => $projectDir ?? null,
+ ]);
+
+ $output->writeln(<<<HTML
+<article data-dedup-id="$dedupIdentifier">
+ <header>
+ <div class="row">
+ <h2 class="col">$title</h2>
+ <time class="col text-small" title="$isoDate" datetime="$isoDate">
+ {$this->extractDate($context)}
+ </time>
+ </div>
+ {$this->renderTags($tags)}
+ </header>
+ <section class="body">
+ <p class="text-small">
+ $sourceDescription
+ </p>
+ {$this->dumper->dump($data, true)}
+ </section>
+</article>
+HTML
+ );
+ }
+
+ private function extractDate(array $context, string $format = 'r'): string
+ {
+ return date($format, (int) $context['timestamp']);
+ }
+
+ private function renderTags(array $tags): string
+ {
+ if (!$tags) {
+ return '';
+ }
+
+ $renderedTags = '';
+ foreach ($tags as $key => $value) {
+ $renderedTags .= sprintf('<li><span class="badge">%s</span>%s</li>', $key, $value);
+ }
+
+ return <<<HTML
+<div class="row">
+ <ul class="tags">
+ $renderedTags
+ </ul>
+</div>
+HTML;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/ServerDumpCommand.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/ServerDumpCommand.php
new file mode 100644
index 0000000..ead9d5b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Command/ServerDumpCommand.php
@@ -0,0 +1,102 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor;
+use Symfony\Component\VarDumper\Command\Descriptor\DumpDescriptorInterface;
+use Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor;
+use Symfony\Component\VarDumper\Dumper\CliDumper;
+use Symfony\Component\VarDumper\Dumper\HtmlDumper;
+use Symfony\Component\VarDumper\Server\DumpServer;
+
+/**
+ * Starts a dump server to collect and output dumps on a single place with multiple formats support.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ *
+ * @final
+ */
+class ServerDumpCommand extends Command
+{
+ protected static $defaultName = 'server:dump';
+ protected static $defaultDescription = 'Start a dump server that collects and displays dumps in a single place';
+
+ private $server;
+
+ /** @var DumpDescriptorInterface[] */
+ private $descriptors;
+
+ public function __construct(DumpServer $server, array $descriptors = [])
+ {
+ $this->server = $server;
+ $this->descriptors = $descriptors + [
+ 'cli' => new CliDescriptor(new CliDumper()),
+ 'html' => new HtmlDescriptor(new HtmlDumper()),
+ ];
+
+ parent::__construct();
+ }
+
+ protected function configure()
+ {
+ $availableFormats = implode(', ', array_keys($this->descriptors));
+
+ $this
+ ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', $availableFormats), 'cli')
+ ->setDescription(self::$defaultDescription)
+ ->setHelp(<<<'EOF'
+<info>%command.name%</info> starts a dump server that collects and displays
+dumps in a single place for debugging you application:
+
+ <info>php %command.full_name%</info>
+
+You can consult dumped data in HTML format in your browser by providing the <comment>--format=html</comment> option
+and redirecting the output to a file:
+
+ <info>php %command.full_name% --format="html" > dump.html</info>
+
+EOF
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $io = new SymfonyStyle($input, $output);
+ $format = $input->getOption('format');
+
+ if (!$descriptor = $this->descriptors[$format] ?? null) {
+ throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $format));
+ }
+
+ $errorIo = $io->getErrorStyle();
+ $errorIo->title('Symfony Var Dumper Server');
+
+ $this->server->start();
+
+ $errorIo->success(sprintf('Server listening on %s', $this->server->getHost()));
+ $errorIo->comment('Quit the server with CONTROL-C.');
+
+ $this->server->listen(function (Data $data, array $context, int $clientId) use ($descriptor, $io) {
+ $descriptor->describe($io, $data, $context, $clientId);
+ });
+
+ return 0;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/AbstractDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/AbstractDumper.php
new file mode 100644
index 0000000..6064ea9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/AbstractDumper.php
@@ -0,0 +1,204 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Dumper;
+
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Cloner\DumperInterface;
+
+/**
+ * Abstract mechanism for dumping a Data object.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+abstract class AbstractDumper implements DataDumperInterface, DumperInterface
+{
+ public const DUMP_LIGHT_ARRAY = 1;
+ public const DUMP_STRING_LENGTH = 2;
+ public const DUMP_COMMA_SEPARATOR = 4;
+ public const DUMP_TRAILING_COMMA = 8;
+
+ public static $defaultOutput = 'php://output';
+
+ protected $line = '';
+ protected $lineDumper;
+ protected $outputStream;
+ protected $decimalPoint; // This is locale dependent
+ protected $indentPad = ' ';
+ protected $flags;
+
+ private $charset = '';
+
+ /**
+ * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput
+ * @param string|null $charset The default character encoding to use for non-UTF8 strings
+ * @param int $flags A bit field of static::DUMP_* constants to fine tune dumps representation
+ */
+ public function __construct($output = null, string $charset = null, int $flags = 0)
+ {
+ $this->flags = $flags;
+ $this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8');
+ $this->decimalPoint = localeconv();
+ $this->decimalPoint = $this->decimalPoint['decimal_point'];
+ $this->setOutput($output ?: static::$defaultOutput);
+ if (!$output && \is_string(static::$defaultOutput)) {
+ static::$defaultOutput = $this->outputStream;
+ }
+ }
+
+ /**
+ * Sets the output destination of the dumps.
+ *
+ * @param callable|resource|string $output A line dumper callable, an opened stream or an output path
+ *
+ * @return callable|resource|string The previous output destination
+ */
+ public function setOutput($output)
+ {
+ $prev = $this->outputStream ?? $this->lineDumper;
+
+ if (\is_callable($output)) {
+ $this->outputStream = null;
+ $this->lineDumper = $output;
+ } else {
+ if (\is_string($output)) {
+ $output = fopen($output, 'w');
+ }
+ $this->outputStream = $output;
+ $this->lineDumper = [$this, 'echoLine'];
+ }
+
+ return $prev;
+ }
+
+ /**
+ * Sets the default character encoding to use for non-UTF8 strings.
+ *
+ * @return string The previous charset
+ */
+ public function setCharset(string $charset)
+ {
+ $prev = $this->charset;
+
+ $charset = strtoupper($charset);
+ $charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset;
+
+ $this->charset = $charset;
+
+ return $prev;
+ }
+
+ /**
+ * Sets the indentation pad string.
+ *
+ * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level
+ *
+ * @return string The previous indent pad
+ */
+ public function setIndentPad(string $pad)
+ {
+ $prev = $this->indentPad;
+ $this->indentPad = $pad;
+
+ return $prev;
+ }
+
+ /**
+ * Dumps a Data object.
+ *
+ * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump
+ *
+ * @return string|null The dump as string when $output is true
+ */
+ public function dump(Data $data, $output = null)
+ {
+ $this->decimalPoint = localeconv();
+ $this->decimalPoint = $this->decimalPoint['decimal_point'];
+
+ if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(\LC_NUMERIC, 0) : null) {
+ setlocale(\LC_NUMERIC, 'C');
+ }
+
+ if ($returnDump = true === $output) {
+ $output = fopen('php://memory', 'r+');
+ }
+ if ($output) {
+ $prevOutput = $this->setOutput($output);
+ }
+ try {
+ $data->dump($this);
+ $this->dumpLine(-1);
+
+ if ($returnDump) {
+ $result = stream_get_contents($output, -1, 0);
+ fclose($output);
+
+ return $result;
+ }
+ } finally {
+ if ($output) {
+ $this->setOutput($prevOutput);
+ }
+ if ($locale) {
+ setlocale(\LC_NUMERIC, $locale);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Dumps the current line.
+ *
+ * @param int $depth The recursive depth in the dumped structure for the line being dumped,
+ * or -1 to signal the end-of-dump to the line dumper callable
+ */
+ protected function dumpLine(int $depth)
+ {
+ ($this->lineDumper)($this->line, $depth, $this->indentPad);
+ $this->line = '';
+ }
+
+ /**
+ * Generic line dumper callback.
+ */
+ protected function echoLine(string $line, int $depth, string $indentPad)
+ {
+ if (-1 !== $depth) {
+ fwrite($this->outputStream, str_repeat($indentPad, $depth).$line."\n");
+ }
+ }
+
+ /**
+ * Converts a non-UTF-8 string to UTF-8.
+ *
+ * @return string|null The string converted to UTF-8
+ */
+ protected function utf8Encode(?string $s)
+ {
+ if (null === $s || preg_match('//u', $s)) {
+ return $s;
+ }
+
+ if (!\function_exists('iconv')) {
+ throw new \RuntimeException('Unable to convert a non-UTF-8 string to UTF-8: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.');
+ }
+
+ if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) {
+ return $c;
+ }
+ if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) {
+ return $c;
+ }
+
+ return iconv('CP850', 'UTF-8', $s);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/CliDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/CliDumper.php
new file mode 100644
index 0000000..c1539ee
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/CliDumper.php
@@ -0,0 +1,643 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Dumper;
+
+use Symfony\Component\VarDumper\Cloner\Cursor;
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * CliDumper dumps variables for command line output.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class CliDumper extends AbstractDumper
+{
+ public static $defaultColors;
+ public static $defaultOutput = 'php://stdout';
+
+ protected $colors;
+ protected $maxStringWidth = 0;
+ protected $styles = [
+ // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
+ 'default' => '0;38;5;208',
+ 'num' => '1;38;5;38',
+ 'const' => '1;38;5;208',
+ 'str' => '1;38;5;113',
+ 'note' => '38;5;38',
+ 'ref' => '38;5;247',
+ 'public' => '',
+ 'protected' => '',
+ 'private' => '',
+ 'meta' => '38;5;170',
+ 'key' => '38;5;113',
+ 'index' => '38;5;38',
+ ];
+
+ protected static $controlCharsRx = '/[\x00-\x1F\x7F]+/';
+ protected static $controlCharsMap = [
+ "\t" => '\t',
+ "\n" => '\n',
+ "\v" => '\v',
+ "\f" => '\f',
+ "\r" => '\r',
+ "\033" => '\e',
+ ];
+
+ protected $collapseNextHash = false;
+ protected $expandNextHash = false;
+
+ private $displayOptions = [
+ 'fileLinkFormat' => null,
+ ];
+
+ private $handlesHrefGracefully;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($output = null, string $charset = null, int $flags = 0)
+ {
+ parent::__construct($output, $charset, $flags);
+
+ if ('\\' === \DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) {
+ // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI
+ $this->setStyles([
+ 'default' => '31',
+ 'num' => '1;34',
+ 'const' => '1;31',
+ 'str' => '1;32',
+ 'note' => '34',
+ 'ref' => '1;30',
+ 'meta' => '35',
+ 'key' => '32',
+ 'index' => '34',
+ ]);
+ }
+
+ $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l';
+ }
+
+ /**
+ * Enables/disables colored output.
+ */
+ public function setColors(bool $colors)
+ {
+ $this->colors = $colors;
+ }
+
+ /**
+ * Sets the maximum number of characters per line for dumped strings.
+ */
+ public function setMaxStringWidth(int $maxStringWidth)
+ {
+ $this->maxStringWidth = $maxStringWidth;
+ }
+
+ /**
+ * Configures styles.
+ *
+ * @param array $styles A map of style names to style definitions
+ */
+ public function setStyles(array $styles)
+ {
+ $this->styles = $styles + $this->styles;
+ }
+
+ /**
+ * Configures display options.
+ *
+ * @param array $displayOptions A map of display options to customize the behavior
+ */
+ public function setDisplayOptions(array $displayOptions)
+ {
+ $this->displayOptions = $displayOptions + $this->displayOptions;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dumpScalar(Cursor $cursor, string $type, $value)
+ {
+ $this->dumpKey($cursor);
+
+ $style = 'const';
+ $attr = $cursor->attr;
+
+ switch ($type) {
+ case 'default':
+ $style = 'default';
+ break;
+
+ case 'integer':
+ $style = 'num';
+ break;
+
+ case 'double':
+ $style = 'num';
+
+ switch (true) {
+ case \INF === $value: $value = 'INF'; break;
+ case -\INF === $value: $value = '-INF'; break;
+ case is_nan($value): $value = 'NAN'; break;
+ default:
+ $value = (string) $value;
+ if (!str_contains($value, $this->decimalPoint)) {
+ $value .= $this->decimalPoint.'0';
+ }
+ break;
+ }
+ break;
+
+ case 'NULL':
+ $value = 'null';
+ break;
+
+ case 'boolean':
+ $value = $value ? 'true' : 'false';
+ break;
+
+ default:
+ $attr += ['value' => $this->utf8Encode($value)];
+ $value = $this->utf8Encode($type);
+ break;
+ }
+
+ $this->line .= $this->style($style, $value, $attr);
+
+ $this->endValue($cursor);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut)
+ {
+ $this->dumpKey($cursor);
+ $attr = $cursor->attr;
+
+ if ($bin) {
+ $str = $this->utf8Encode($str);
+ }
+ if ('' === $str) {
+ $this->line .= '""';
+ $this->endValue($cursor);
+ } else {
+ $attr += [
+ 'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0,
+ 'binary' => $bin,
+ ];
+ $str = $bin && false !== strpos($str, "\0") ? [$str] : explode("\n", $str);
+ if (isset($str[1]) && !isset($str[2]) && !isset($str[1][0])) {
+ unset($str[1]);
+ $str[0] .= "\n";
+ }
+ $m = \count($str) - 1;
+ $i = $lineCut = 0;
+
+ if (self::DUMP_STRING_LENGTH & $this->flags) {
+ $this->line .= '('.$attr['length'].') ';
+ }
+ if ($bin) {
+ $this->line .= 'b';
+ }
+
+ if ($m) {
+ $this->line .= '"""';
+ $this->dumpLine($cursor->depth);
+ } else {
+ $this->line .= '"';
+ }
+
+ foreach ($str as $str) {
+ if ($i < $m) {
+ $str .= "\n";
+ }
+ if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) {
+ $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8');
+ $lineCut = $len - $this->maxStringWidth;
+ }
+ if ($m && 0 < $cursor->depth) {
+ $this->line .= $this->indentPad;
+ }
+ if ('' !== $str) {
+ $this->line .= $this->style('str', $str, $attr);
+ }
+ if ($i++ == $m) {
+ if ($m) {
+ if ('' !== $str) {
+ $this->dumpLine($cursor->depth);
+ if (0 < $cursor->depth) {
+ $this->line .= $this->indentPad;
+ }
+ }
+ $this->line .= '"""';
+ } else {
+ $this->line .= '"';
+ }
+ if ($cut < 0) {
+ $this->line .= '…';
+ $lineCut = 0;
+ } elseif ($cut) {
+ $lineCut += $cut;
+ }
+ }
+ if ($lineCut) {
+ $this->line .= '…'.$lineCut;
+ $lineCut = 0;
+ }
+
+ if ($i > $m) {
+ $this->endValue($cursor);
+ } else {
+ $this->dumpLine($cursor->depth);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild)
+ {
+ if (null === $this->colors) {
+ $this->colors = $this->supportsColors();
+ }
+
+ $this->dumpKey($cursor);
+ $attr = $cursor->attr;
+
+ if ($this->collapseNextHash) {
+ $cursor->skipChildren = true;
+ $this->collapseNextHash = $hasChild = false;
+ }
+
+ $class = $this->utf8Encode($class);
+ if (Cursor::HASH_OBJECT === $type) {
+ $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).(empty($attr['cut_hash']) ? ' {' : '') : '{';
+ } elseif (Cursor::HASH_RESOURCE === $type) {
+ $prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' ');
+ } else {
+ $prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class).' [' : '[';
+ }
+
+ if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) {
+ $prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#').(0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]);
+ } elseif ($cursor->hardRefTo && !$cursor->refIndex && $class) {
+ $prefix .= $this->style('ref', '&'.$cursor->hardRefTo, ['count' => $cursor->hardRefCount]);
+ } elseif (!$hasChild && Cursor::HASH_RESOURCE === $type) {
+ $prefix = substr($prefix, 0, -1);
+ }
+
+ $this->line .= $prefix;
+
+ if ($hasChild) {
+ $this->dumpLine($cursor->depth);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut)
+ {
+ if (empty($cursor->attr['cut_hash'])) {
+ $this->dumpEllipsis($cursor, $hasChild, $cut);
+ $this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : ''));
+ }
+
+ $this->endValue($cursor);
+ }
+
+ /**
+ * Dumps an ellipsis for cut children.
+ *
+ * @param bool $hasChild When the dump of the hash has child item
+ * @param int $cut The number of items the hash has been cut by
+ */
+ protected function dumpEllipsis(Cursor $cursor, bool $hasChild, int $cut)
+ {
+ if ($cut) {
+ $this->line .= ' …';
+ if (0 < $cut) {
+ $this->line .= $cut;
+ }
+ if ($hasChild) {
+ $this->dumpLine($cursor->depth + 1);
+ }
+ }
+ }
+
+ /**
+ * Dumps a key in a hash structure.
+ */
+ protected function dumpKey(Cursor $cursor)
+ {
+ if (null !== $key = $cursor->hashKey) {
+ if ($cursor->hashKeyIsBinary) {
+ $key = $this->utf8Encode($key);
+ }
+ $attr = ['binary' => $cursor->hashKeyIsBinary];
+ $bin = $cursor->hashKeyIsBinary ? 'b' : '';
+ $style = 'key';
+ switch ($cursor->hashType) {
+ default:
+ case Cursor::HASH_INDEXED:
+ if (self::DUMP_LIGHT_ARRAY & $this->flags) {
+ break;
+ }
+ $style = 'index';
+ // no break
+ case Cursor::HASH_ASSOC:
+ if (\is_int($key)) {
+ $this->line .= $this->style($style, $key).' => ';
+ } else {
+ $this->line .= $bin.'"'.$this->style($style, $key).'" => ';
+ }
+ break;
+
+ case Cursor::HASH_RESOURCE:
+ $key = "\0~\0".$key;
+ // no break
+ case Cursor::HASH_OBJECT:
+ if (!isset($key[0]) || "\0" !== $key[0]) {
+ $this->line .= '+'.$bin.$this->style('public', $key).': ';
+ } elseif (0 < strpos($key, "\0", 1)) {
+ $key = explode("\0", substr($key, 1), 2);
+
+ switch ($key[0][0]) {
+ case '+': // User inserted keys
+ $attr['dynamic'] = true;
+ $this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": ';
+ break 2;
+ case '~':
+ $style = 'meta';
+ if (isset($key[0][1])) {
+ parse_str(substr($key[0], 1), $attr);
+ $attr += ['binary' => $cursor->hashKeyIsBinary];
+ }
+ break;
+ case '*':
+ $style = 'protected';
+ $bin = '#'.$bin;
+ break;
+ default:
+ $attr['class'] = $key[0];
+ $style = 'private';
+ $bin = '-'.$bin;
+ break;
+ }
+
+ if (isset($attr['collapse'])) {
+ if ($attr['collapse']) {
+ $this->collapseNextHash = true;
+ } else {
+ $this->expandNextHash = true;
+ }
+ }
+
+ $this->line .= $bin.$this->style($style, $key[1], $attr).($attr['separator'] ?? ': ');
+ } else {
+ // This case should not happen
+ $this->line .= '-'.$bin.'"'.$this->style('private', $key, ['class' => '']).'": ';
+ }
+ break;
+ }
+
+ if ($cursor->hardRefTo) {
+ $this->line .= $this->style('ref', '&'.($cursor->hardRefCount ? $cursor->hardRefTo : ''), ['count' => $cursor->hardRefCount]).' ';
+ }
+ }
+ }
+
+ /**
+ * Decorates a value with some style.
+ *
+ * @param string $style The type of style being applied
+ * @param string $value The value being styled
+ * @param array $attr Optional context information
+ *
+ * @return string The value with style decoration
+ */
+ protected function style(string $style, string $value, array $attr = [])
+ {
+ if (null === $this->colors) {
+ $this->colors = $this->supportsColors();
+ }
+
+ if (null === $this->handlesHrefGracefully) {
+ $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR')
+ && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100);
+ }
+
+ if (isset($attr['ellipsis'], $attr['ellipsis-type'])) {
+ $prefix = substr($value, 0, -$attr['ellipsis']);
+ if ('cli' === \PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === \DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && str_starts_with($prefix, $_SERVER[$pwd])) {
+ $prefix = '.'.substr($prefix, \strlen($_SERVER[$pwd]));
+ }
+ if (!empty($attr['ellipsis-tail'])) {
+ $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']);
+ $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']);
+ } else {
+ $value = substr($value, -$attr['ellipsis']);
+ }
+
+ $value = $this->style('default', $prefix).$this->style($style, $value);
+
+ goto href;
+ }
+
+ $map = static::$controlCharsMap;
+ $startCchr = $this->colors ? "\033[m\033[{$this->styles['default']}m" : '';
+ $endCchr = $this->colors ? "\033[m\033[{$this->styles[$style]}m" : '';
+ $value = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $startCchr, $endCchr) {
+ $s = $startCchr;
+ $c = $c[$i = 0];
+ do {
+ $s .= $map[$c[$i]] ?? sprintf('\x%02X', \ord($c[$i]));
+ } while (isset($c[++$i]));
+
+ return $s.$endCchr;
+ }, $value, -1, $cchrCount);
+
+ if ($this->colors) {
+ if ($cchrCount && "\033" === $value[0]) {
+ $value = substr($value, \strlen($startCchr));
+ } else {
+ $value = "\033[{$this->styles[$style]}m".$value;
+ }
+ if ($cchrCount && str_ends_with($value, $endCchr)) {
+ $value = substr($value, 0, -\strlen($endCchr));
+ } else {
+ $value .= "\033[{$this->styles['default']}m";
+ }
+ }
+
+ href:
+ if ($this->colors && $this->handlesHrefGracefully) {
+ if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) {
+ if ('note' === $style) {
+ $value .= "\033]8;;{$href}\033\\^\033]8;;\033\\";
+ } else {
+ $attr['href'] = $href;
+ }
+ }
+ if (isset($attr['href'])) {
+ $value = "\033]8;;{$attr['href']}\033\\{$value}\033]8;;\033\\";
+ }
+ } elseif ($attr['if_links'] ?? false) {
+ return '';
+ }
+
+ return $value;
+ }
+
+ /**
+ * @return bool Tells if the current output stream supports ANSI colors or not
+ */
+ protected function supportsColors()
+ {
+ if ($this->outputStream !== static::$defaultOutput) {
+ return $this->hasColorSupport($this->outputStream);
+ }
+ if (null !== static::$defaultColors) {
+ return static::$defaultColors;
+ }
+ if (isset($_SERVER['argv'][1])) {
+ $colors = $_SERVER['argv'];
+ $i = \count($colors);
+ while (--$i > 0) {
+ if (isset($colors[$i][5])) {
+ switch ($colors[$i]) {
+ case '--ansi':
+ case '--color':
+ case '--color=yes':
+ case '--color=force':
+ case '--color=always':
+ case '--colors=always':
+ return static::$defaultColors = true;
+
+ case '--no-ansi':
+ case '--color=no':
+ case '--color=none':
+ case '--color=never':
+ case '--colors=never':
+ return static::$defaultColors = false;
+ }
+ }
+ }
+ }
+
+ $h = stream_get_meta_data($this->outputStream) + ['wrapper_type' => null];
+ $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'w') : $this->outputStream;
+
+ return static::$defaultColors = $this->hasColorSupport($h);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function dumpLine(int $depth, bool $endOfValue = false)
+ {
+ if ($this->colors) {
+ $this->line = sprintf("\033[%sm%s\033[m", $this->styles['default'], $this->line);
+ }
+ parent::dumpLine($depth);
+ }
+
+ protected function endValue(Cursor $cursor)
+ {
+ if (-1 === $cursor->hashType) {
+ return;
+ }
+
+ if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) {
+ if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) {
+ $this->line .= ',';
+ } elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) {
+ $this->line .= ',';
+ }
+ }
+
+ $this->dumpLine($cursor->depth, true);
+ }
+
+ /**
+ * Returns true if the stream supports colorization.
+ *
+ * Reference: Composer\XdebugHandler\Process::supportsColor
+ * https://github.com/composer/xdebug-handler
+ *
+ * @param mixed $stream A CLI output stream
+ */
+ private function hasColorSupport($stream): bool
+ {
+ if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) {
+ return false;
+ }
+
+ // Follow https://no-color.org/
+ if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) {
+ return false;
+ }
+
+ if ('Hyper' === getenv('TERM_PROGRAM')) {
+ return true;
+ }
+
+ if (\DIRECTORY_SEPARATOR === '\\') {
+ return (\function_exists('sapi_windows_vt100_support')
+ && @sapi_windows_vt100_support($stream))
+ || false !== getenv('ANSICON')
+ || 'ON' === getenv('ConEmuANSI')
+ || 'xterm' === getenv('TERM');
+ }
+
+ return stream_isatty($stream);
+ }
+
+ /**
+ * Returns true if the Windows terminal supports true color.
+ *
+ * Note that this does not check an output stream, but relies on environment
+ * variables from known implementations, or a PHP and Windows version that
+ * supports true color.
+ */
+ private function isWindowsTrueColor(): bool
+ {
+ $result = 183 <= getenv('ANSICON_VER')
+ || 'ON' === getenv('ConEmuANSI')
+ || 'xterm' === getenv('TERM')
+ || 'Hyper' === getenv('TERM_PROGRAM');
+
+ if (!$result) {
+ $version = sprintf(
+ '%s.%s.%s',
+ PHP_WINDOWS_VERSION_MAJOR,
+ PHP_WINDOWS_VERSION_MINOR,
+ PHP_WINDOWS_VERSION_BUILD
+ );
+ $result = $version >= '10.0.15063';
+ }
+
+ return $result;
+ }
+
+ private function getSourceLink(string $file, int $line)
+ {
+ if ($fmt = $this->displayOptions['fileLinkFormat']) {
+ return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file.'#L'.$line);
+ }
+
+ return false;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php
new file mode 100644
index 0000000..38f8789
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Dumper\ContextProvider;
+
+/**
+ * Tries to provide context on CLI.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+final class CliContextProvider implements ContextProviderInterface
+{
+ public function getContext(): ?array
+ {
+ if ('cli' !== \PHP_SAPI) {
+ return null;
+ }
+
+ return [
+ 'command_line' => $commandLine = implode(' ', $_SERVER['argv'] ?? []),
+ 'identifier' => hash('crc32b', $commandLine.$_SERVER['REQUEST_TIME_FLOAT']),
+ ];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php
new file mode 100644
index 0000000..38ef3b0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Dumper\ContextProvider;
+
+/**
+ * Interface to provide contextual data about dump data clones sent to a server.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+interface ContextProviderInterface
+{
+ /**
+ * @return array|null Context data or null if unable to provide any context
+ */
+ public function getContext(): ?array;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php
new file mode 100644
index 0000000..3684a47
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Dumper\ContextProvider;
+
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\VarDumper\Caster\ReflectionCaster;
+use Symfony\Component\VarDumper\Cloner\VarCloner;
+
+/**
+ * Tries to provide context from a request.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+final class RequestContextProvider implements ContextProviderInterface
+{
+ private $requestStack;
+ private $cloner;
+
+ public function __construct(RequestStack $requestStack)
+ {
+ $this->requestStack = $requestStack;
+ $this->cloner = new VarCloner();
+ $this->cloner->setMaxItems(0);
+ $this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);
+ }
+
+ public function getContext(): ?array
+ {
+ if (null === $request = $this->requestStack->getCurrentRequest()) {
+ return null;
+ }
+
+ $controller = $request->attributes->get('_controller');
+
+ return [
+ 'uri' => $request->getUri(),
+ 'method' => $request->getMethod(),
+ 'controller' => $controller ? $this->cloner->cloneVar($controller) : $controller,
+ 'identifier' => spl_object_hash($request),
+ ];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php
new file mode 100644
index 0000000..2e2c818
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php
@@ -0,0 +1,126 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Dumper\ContextProvider;
+
+use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
+use Symfony\Component\VarDumper\Cloner\VarCloner;
+use Symfony\Component\VarDumper\Dumper\HtmlDumper;
+use Symfony\Component\VarDumper\VarDumper;
+use Twig\Template;
+
+/**
+ * Tries to provide context from sources (class name, file, line, code excerpt, ...).
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+final class SourceContextProvider implements ContextProviderInterface
+{
+ private $limit;
+ private $charset;
+ private $projectDir;
+ private $fileLinkFormatter;
+
+ public function __construct(string $charset = null, string $projectDir = null, FileLinkFormatter $fileLinkFormatter = null, int $limit = 9)
+ {
+ $this->charset = $charset;
+ $this->projectDir = $projectDir;
+ $this->fileLinkFormatter = $fileLinkFormatter;
+ $this->limit = $limit;
+ }
+
+ public function getContext(): ?array
+ {
+ $trace = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, $this->limit);
+
+ $file = $trace[1]['file'];
+ $line = $trace[1]['line'];
+ $name = false;
+ $fileExcerpt = false;
+
+ for ($i = 2; $i < $this->limit; ++$i) {
+ if (isset($trace[$i]['class'], $trace[$i]['function'])
+ && 'dump' === $trace[$i]['function']
+ && VarDumper::class === $trace[$i]['class']
+ ) {
+ $file = $trace[$i]['file'] ?? $file;
+ $line = $trace[$i]['line'] ?? $line;
+
+ while (++$i < $this->limit) {
+ if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && !str_starts_with($trace[$i]['function'], 'call_user_func')) {
+ $file = $trace[$i]['file'];
+ $line = $trace[$i]['line'];
+
+ break;
+ } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) {
+ $template = $trace[$i]['object'];
+ $name = $template->getTemplateName();
+ $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false);
+ $info = $template->getDebugInfo();
+ if (isset($info[$trace[$i - 1]['line']])) {
+ $line = $info[$trace[$i - 1]['line']];
+ $file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null;
+
+ if ($src) {
+ $src = explode("\n", $src);
+ $fileExcerpt = [];
+
+ for ($i = max($line - 3, 1), $max = min($line + 3, \count($src)); $i <= $max; ++$i) {
+ $fileExcerpt[] = '<li'.($i === $line ? ' class="selected"' : '').'><code>'.$this->htmlEncode($src[$i - 1]).'</code></li>';
+ }
+
+ $fileExcerpt = '<ol start="'.max($line - 3, 1).'">'.implode("\n", $fileExcerpt).'</ol>';
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if (false === $name) {
+ $name = str_replace('\\', '/', $file);
+ $name = substr($name, strrpos($name, '/') + 1);
+ }
+
+ $context = ['name' => $name, 'file' => $file, 'line' => $line];
+ $context['file_excerpt'] = $fileExcerpt;
+
+ if (null !== $this->projectDir) {
+ $context['project_dir'] = $this->projectDir;
+ if (str_starts_with($file, $this->projectDir)) {
+ $context['file_relative'] = ltrim(substr($file, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
+ }
+ }
+
+ if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file'], $context['line'])) {
+ $context['file_link'] = $fileLink;
+ }
+
+ return $context;
+ }
+
+ private function htmlEncode(string $s): string
+ {
+ $html = '';
+
+ $dumper = new HtmlDumper(function ($line) use (&$html) { $html .= $line; }, $this->charset);
+ $dumper->setDumpHeader('');
+ $dumper->setDumpBoundaries('', '');
+
+ $cloner = new VarCloner();
+ $dumper->dump($cloner->cloneVar($s));
+
+ return substr(strip_tags($html), 1, -1);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php
new file mode 100644
index 0000000..7638417
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Dumper;
+
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
+
+/**
+ * @author Kévin Thérage <therage.kevin@gmail.com>
+ */
+class ContextualizedDumper implements DataDumperInterface
+{
+ private $wrappedDumper;
+ private $contextProviders;
+
+ /**
+ * @param ContextProviderInterface[] $contextProviders
+ */
+ public function __construct(DataDumperInterface $wrappedDumper, array $contextProviders)
+ {
+ $this->wrappedDumper = $wrappedDumper;
+ $this->contextProviders = $contextProviders;
+ }
+
+ public function dump(Data $data)
+ {
+ $context = [];
+ foreach ($this->contextProviders as $contextProvider) {
+ $context[\get_class($contextProvider)] = $contextProvider->getContext();
+ }
+
+ $this->wrappedDumper->dump($data->withContext($context));
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php
new file mode 100644
index 0000000..b173bcc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Dumper;
+
+use Symfony\Component\VarDumper\Cloner\Data;
+
+/**
+ * DataDumperInterface for dumping Data objects.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+interface DataDumperInterface
+{
+ public function dump(Data $data);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/HtmlDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/HtmlDumper.php
new file mode 100644
index 0000000..6c3abaa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/HtmlDumper.php
@@ -0,0 +1,986 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Dumper;
+
+use Symfony\Component\VarDumper\Cloner\Cursor;
+use Symfony\Component\VarDumper\Cloner\Data;
+
+/**
+ * HtmlDumper dumps variables as HTML.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class HtmlDumper extends CliDumper
+{
+ public static $defaultOutput = 'php://output';
+
+ protected static $themes = [
+ 'dark' => [
+ 'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all',
+ 'num' => 'font-weight:bold; color:#1299DA',
+ 'const' => 'font-weight:bold',
+ 'str' => 'font-weight:bold; color:#56DB3A',
+ 'note' => 'color:#1299DA',
+ 'ref' => 'color:#A0A0A0',
+ 'public' => 'color:#FFFFFF',
+ 'protected' => 'color:#FFFFFF',
+ 'private' => 'color:#FFFFFF',
+ 'meta' => 'color:#B729D9',
+ 'key' => 'color:#56DB3A',
+ 'index' => 'color:#1299DA',
+ 'ellipsis' => 'color:#FF8400',
+ 'ns' => 'user-select:none;',
+ ],
+ 'light' => [
+ 'default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all',
+ 'num' => 'font-weight:bold; color:#1299DA',
+ 'const' => 'font-weight:bold',
+ 'str' => 'font-weight:bold; color:#629755;',
+ 'note' => 'color:#6897BB',
+ 'ref' => 'color:#6E6E6E',
+ 'public' => 'color:#262626',
+ 'protected' => 'color:#262626',
+ 'private' => 'color:#262626',
+ 'meta' => 'color:#B729D9',
+ 'key' => 'color:#789339',
+ 'index' => 'color:#1299DA',
+ 'ellipsis' => 'color:#CC7832',
+ 'ns' => 'user-select:none;',
+ ],
+ ];
+
+ protected $dumpHeader;
+ protected $dumpPrefix = '<pre class=sf-dump id=%s data-indent-pad="%s">';
+ protected $dumpSuffix = '</pre><script>Sfdump(%s)</script>';
+ protected $dumpId = 'sf-dump';
+ protected $colors = true;
+ protected $headerIsDumped = false;
+ protected $lastDepth = -1;
+ protected $styles;
+
+ private $displayOptions = [
+ 'maxDepth' => 1,
+ 'maxStringLength' => 160,
+ 'fileLinkFormat' => null,
+ ];
+ private $extraDisplayOptions = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($output = null, string $charset = null, int $flags = 0)
+ {
+ AbstractDumper::__construct($output, $charset, $flags);
+ $this->dumpId = 'sf-dump-'.mt_rand();
+ $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
+ $this->styles = static::$themes['dark'] ?? self::$themes['dark'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setStyles(array $styles)
+ {
+ $this->headerIsDumped = false;
+ $this->styles = $styles + $this->styles;
+ }
+
+ public function setTheme(string $themeName)
+ {
+ if (!isset(static::$themes[$themeName])) {
+ throw new \InvalidArgumentException(sprintf('Theme "%s" does not exist in class "%s".', $themeName, static::class));
+ }
+
+ $this->setStyles(static::$themes[$themeName]);
+ }
+
+ /**
+ * Configures display options.
+ *
+ * @param array $displayOptions A map of display options to customize the behavior
+ */
+ public function setDisplayOptions(array $displayOptions)
+ {
+ $this->headerIsDumped = false;
+ $this->displayOptions = $displayOptions + $this->displayOptions;
+ }
+
+ /**
+ * Sets an HTML header that will be dumped once in the output stream.
+ */
+ public function setDumpHeader(?string $header)
+ {
+ $this->dumpHeader = $header;
+ }
+
+ /**
+ * Sets an HTML prefix and suffix that will encapse every single dump.
+ */
+ public function setDumpBoundaries(string $prefix, string $suffix)
+ {
+ $this->dumpPrefix = $prefix;
+ $this->dumpSuffix = $suffix;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dump(Data $data, $output = null, array $extraDisplayOptions = [])
+ {
+ $this->extraDisplayOptions = $extraDisplayOptions;
+ $result = parent::dump($data, $output);
+ $this->dumpId = 'sf-dump-'.mt_rand();
+
+ return $result;
+ }
+
+ /**
+ * Dumps the HTML header.
+ */
+ protected function getDumpHeader()
+ {
+ $this->headerIsDumped = $this->outputStream ?? $this->lineDumper;
+
+ if (null !== $this->dumpHeader) {
+ return $this->dumpHeader;
+ }
+
+ $line = str_replace('{$options}', json_encode($this->displayOptions, \JSON_FORCE_OBJECT), <<<'EOHTML'
+<script>
+Sfdump = window.Sfdump || (function (doc) {
+
+var refStyle = doc.createElement('style'),
+ rxEsc = /([.*+?^${}()|\[\]\/\\])/g,
+ idRx = /\bsf-dump-\d+-ref[012]\w+\b/,
+ keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl',
+ addEventListener = function (e, n, cb) {
+ e.addEventListener(n, cb, false);
+ };
+
+refStyle.innerHTML = 'pre.sf-dump .sf-dump-compact, .sf-dump-str-collapse .sf-dump-str-collapse, .sf-dump-str-expand .sf-dump-str-expand { display: none; }';
+(doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle);
+refStyle = doc.createElement('style');
+(doc.documentElement.firstElementChild || doc.documentElement.children[0]).appendChild(refStyle);
+
+if (!doc.addEventListener) {
+ addEventListener = function (element, eventName, callback) {
+ element.attachEvent('on' + eventName, function (e) {
+ e.preventDefault = function () {e.returnValue = false;};
+ e.target = e.srcElement;
+ callback(e);
+ });
+ };
+}
+
+function toggle(a, recursive) {
+ var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass;
+
+ if (/\bsf-dump-compact\b/.test(oldClass)) {
+ arrow = '▼';
+ newClass = 'sf-dump-expanded';
+ } else if (/\bsf-dump-expanded\b/.test(oldClass)) {
+ arrow = '▶';
+ newClass = 'sf-dump-compact';
+ } else {
+ return false;
+ }
+
+ if (doc.createEvent && s.dispatchEvent) {
+ var event = doc.createEvent('Event');
+ event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false);
+
+ s.dispatchEvent(event);
+ }
+
+ a.lastChild.innerHTML = arrow;
+ s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass);
+
+ if (recursive) {
+ try {
+ a = s.querySelectorAll('.'+oldClass);
+ for (s = 0; s < a.length; ++s) {
+ if (-1 == a[s].className.indexOf(newClass)) {
+ a[s].className = newClass;
+ a[s].previousSibling.lastChild.innerHTML = arrow;
+ }
+ }
+ } catch (e) {
+ }
+ }
+
+ return true;
+};
+
+function collapse(a, recursive) {
+ var s = a.nextSibling || {}, oldClass = s.className;
+
+ if (/\bsf-dump-expanded\b/.test(oldClass)) {
+ toggle(a, recursive);
+
+ return true;
+ }
+
+ return false;
+};
+
+function expand(a, recursive) {
+ var s = a.nextSibling || {}, oldClass = s.className;
+
+ if (/\bsf-dump-compact\b/.test(oldClass)) {
+ toggle(a, recursive);
+
+ return true;
+ }
+
+ return false;
+};
+
+function collapseAll(root) {
+ var a = root.querySelector('a.sf-dump-toggle');
+ if (a) {
+ collapse(a, true);
+ expand(a);
+
+ return true;
+ }
+
+ return false;
+}
+
+function reveal(node) {
+ var previous, parents = [];
+
+ while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) {
+ parents.push(previous);
+ }
+
+ if (0 !== parents.length) {
+ parents.forEach(function (parent) {
+ expand(parent);
+ });
+
+ return true;
+ }
+
+ return false;
+}
+
+function highlight(root, activeNode, nodes) {
+ resetHighlightedNodes(root);
+
+ Array.from(nodes||[]).forEach(function (node) {
+ if (!/\bsf-dump-highlight\b/.test(node.className)) {
+ node.className = node.className + ' sf-dump-highlight';
+ }
+ });
+
+ if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) {
+ activeNode.className = activeNode.className + ' sf-dump-highlight-active';
+ }
+}
+
+function resetHighlightedNodes(root) {
+ Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) {
+ strNode.className = strNode.className.replace(/\bsf-dump-highlight\b/, '');
+ strNode.className = strNode.className.replace(/\bsf-dump-highlight-active\b/, '');
+ });
+}
+
+return function (root, x) {
+ root = doc.getElementById(root);
+
+ var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'),
+ options = {$options},
+ elt = root.getElementsByTagName('A'),
+ len = elt.length,
+ i = 0, s, h,
+ t = [];
+
+ while (i < len) t.push(elt[i++]);
+
+ for (i in x) {
+ options[i] = x[i];
+ }
+
+ function a(e, f) {
+ addEventListener(root, e, function (e, n) {
+ if ('A' == e.target.tagName) {
+ f(e.target, e);
+ } else if ('A' == e.target.parentNode.tagName) {
+ f(e.target.parentNode, e);
+ } else {
+ n = /\bsf-dump-ellipsis\b/.test(e.target.className) ? e.target.parentNode : e.target;
+
+ if ((n = n.nextElementSibling) && 'A' == n.tagName) {
+ if (!/\bsf-dump-toggle\b/.test(n.className)) {
+ n = n.nextElementSibling || n;
+ }
+
+ f(n, e, true);
+ }
+ }
+ });
+ };
+ function isCtrlKey(e) {
+ return e.ctrlKey || e.metaKey;
+ }
+ function xpathString(str) {
+ var parts = str.match(/[^'"]+|['"]/g).map(function (part) {
+ if ("'" == part) {
+ return '"\'"';
+ }
+ if ('"' == part) {
+ return "'\"'";
+ }
+
+ return "'" + part + "'";
+ });
+
+ return "concat(" + parts.join(",") + ", '')";
+ }
+ function xpathHasClass(className) {
+ return "contains(concat(' ', normalize-space(@class), ' '), ' " + className +" ')";
+ }
+ addEventListener(root, 'mouseover', function (e) {
+ if ('' != refStyle.innerHTML) {
+ refStyle.innerHTML = '';
+ }
+ });
+ a('mouseover', function (a, e, c) {
+ if (c) {
+ e.target.style.cursor = "pointer";
+ } else if (a = idRx.exec(a.className)) {
+ try {
+ refStyle.innerHTML = 'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF !important; border-radius: 2px}';
+ } catch (e) {
+ }
+ }
+ });
+ a('click', function (a, e, c) {
+ if (/\bsf-dump-toggle\b/.test(a.className)) {
+ e.preventDefault();
+ if (!toggle(a, isCtrlKey(e))) {
+ var r = doc.getElementById(a.getAttribute('href').substr(1)),
+ s = r.previousSibling,
+ f = r.parentNode,
+ t = a.parentNode;
+ t.replaceChild(r, a);
+ f.replaceChild(a, s);
+ t.insertBefore(s, r);
+ f = f.firstChild.nodeValue.match(indentRx);
+ t = t.firstChild.nodeValue.match(indentRx);
+ if (f && t && f[0] !== t[0]) {
+ r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]);
+ }
+ if (/\bsf-dump-compact\b/.test(r.className)) {
+ toggle(s, isCtrlKey(e));
+ }
+ }
+
+ if (c) {
+ } else if (doc.getSelection) {
+ try {
+ doc.getSelection().removeAllRanges();
+ } catch (e) {
+ doc.getSelection().empty();
+ }
+ } else {
+ doc.selection.empty();
+ }
+ } else if (/\bsf-dump-str-toggle\b/.test(a.className)) {
+ e.preventDefault();
+ e = a.parentNode.parentNode;
+ e.className = e.className.replace(/\bsf-dump-str-(expand|collapse)\b/, a.parentNode.className);
+ }
+ });
+
+ elt = root.getElementsByTagName('SAMP');
+ len = elt.length;
+ i = 0;
+
+ while (i < len) t.push(elt[i++]);
+ len = t.length;
+
+ for (i = 0; i < len; ++i) {
+ elt = t[i];
+ if ('SAMP' == elt.tagName) {
+ a = elt.previousSibling || {};
+ if ('A' != a.tagName) {
+ a = doc.createElement('A');
+ a.className = 'sf-dump-ref';
+ elt.parentNode.insertBefore(a, elt);
+ } else {
+ a.innerHTML += ' ';
+ }
+ a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children';
+ a.innerHTML += elt.className == 'sf-dump-compact' ? '<span>▶</span>' : '<span>▼</span>';
+ a.className += ' sf-dump-toggle';
+
+ x = 1;
+ if ('sf-dump' != elt.parentNode.className) {
+ x += elt.parentNode.getAttribute('data-depth')/1;
+ }
+ } else if (/\bsf-dump-ref\b/.test(elt.className) && (a = elt.getAttribute('href'))) {
+ a = a.substr(1);
+ elt.className += ' '+a;
+
+ if (/[\[{]$/.test(elt.previousSibling.nodeValue)) {
+ a = a != elt.nextSibling.id && doc.getElementById(a);
+ try {
+ s = a.nextSibling;
+ elt.appendChild(a);
+ s.parentNode.insertBefore(a, s);
+ if (/^[@#]/.test(elt.innerHTML)) {
+ elt.innerHTML += ' <span>▶</span>';
+ } else {
+ elt.innerHTML = '<span>▶</span>';
+ elt.className = 'sf-dump-ref';
+ }
+ elt.className += ' sf-dump-toggle';
+ } catch (e) {
+ if ('&' == elt.innerHTML.charAt(0)) {
+ elt.innerHTML = '…';
+ elt.className = 'sf-dump-ref';
+ }
+ }
+ }
+ }
+ }
+
+ if (doc.evaluate && Array.from && root.children.length > 1) {
+ root.setAttribute('tabindex', 0);
+
+ SearchState = function () {
+ this.nodes = [];
+ this.idx = 0;
+ };
+ SearchState.prototype = {
+ next: function () {
+ if (this.isEmpty()) {
+ return this.current();
+ }
+ this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0;
+
+ return this.current();
+ },
+ previous: function () {
+ if (this.isEmpty()) {
+ return this.current();
+ }
+ this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1);
+
+ return this.current();
+ },
+ isEmpty: function () {
+ return 0 === this.count();
+ },
+ current: function () {
+ if (this.isEmpty()) {
+ return null;
+ }
+ return this.nodes[this.idx];
+ },
+ reset: function () {
+ this.nodes = [];
+ this.idx = 0;
+ },
+ count: function () {
+ return this.nodes.length;
+ },
+ };
+
+ function showCurrent(state)
+ {
+ var currentNode = state.current(), currentRect, searchRect;
+ if (currentNode) {
+ reveal(currentNode);
+ highlight(root, currentNode, state.nodes);
+ if ('scrollIntoView' in currentNode) {
+ currentNode.scrollIntoView(true);
+ currentRect = currentNode.getBoundingClientRect();
+ searchRect = search.getBoundingClientRect();
+ if (currentRect.top < (searchRect.top + searchRect.height)) {
+ window.scrollBy(0, -(searchRect.top + searchRect.height + 5));
+ }
+ }
+ }
+ counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' of ' + state.count();
+ }
+
+ var search = doc.createElement('div');
+ search.className = 'sf-dump-search-wrapper sf-dump-search-hidden';
+ search.innerHTML = '
+ <input type="text" class="sf-dump-search-input">
+ <span class="sf-dump-search-count">0 of 0<\/span>
+ <button type="button" class="sf-dump-search-input-previous" tabindex="-1">
+ <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 1331l-166 165q-19 19-45 19t-45-19L896 965l-531 531q-19 19-45 19t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19 45-19t45 19l742 741q19 19 19 45.5t-19 45.5z"\/><\/svg>
+ <\/button>
+ <button type="button" class="sf-dump-search-input-next" tabindex="-1">
+ <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 808l-742 741q-19 19-45 19t-45-19L109 808q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z"\/><\/svg>
+ <\/button>
+ ';
+ root.insertBefore(search, root.firstChild);
+
+ var state = new SearchState();
+ var searchInput = search.querySelector('.sf-dump-search-input');
+ var counter = search.querySelector('.sf-dump-search-count');
+ var searchInputTimer = 0;
+ var previousSearchQuery = '';
+
+ addEventListener(searchInput, 'keyup', function (e) {
+ var searchQuery = e.target.value;
+ /* Don't perform anything if the pressed key didn't change the query */
+ if (searchQuery === previousSearchQuery) {
+ return;
+ }
+ previousSearchQuery = searchQuery;
+ clearTimeout(searchInputTimer);
+ searchInputTimer = setTimeout(function () {
+ state.reset();
+ collapseAll(root);
+ resetHighlightedNodes(root);
+ if ('' === searchQuery) {
+ counter.textContent = '0 of 0';
+
+ return;
+ }
+
+ var classMatches = [
+ "sf-dump-str",
+ "sf-dump-key",
+ "sf-dump-public",
+ "sf-dump-protected",
+ "sf-dump-private",
+ ].map(xpathHasClass).join(' or ');
+
+ var xpathResult = doc.evaluate('.//span[' + classMatches + '][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
+
+ while (node = xpathResult.iterateNext()) state.nodes.push(node);
+
+ showCurrent(state);
+ }, 400);
+ });
+
+ Array.from(search.querySelectorAll('.sf-dump-search-input-next, .sf-dump-search-input-previous')).forEach(function (btn) {
+ addEventListener(btn, 'click', function (e) {
+ e.preventDefault();
+ -1 !== e.target.className.indexOf('next') ? state.next() : state.previous();
+ searchInput.focus();
+ collapseAll(root);
+ showCurrent(state);
+ })
+ });
+
+ addEventListener(root, 'keydown', function (e) {
+ var isSearchActive = !/\bsf-dump-search-hidden\b/.test(search.className);
+ if ((114 === e.keyCode && !isSearchActive) || (isCtrlKey(e) && 70 === e.keyCode)) {
+ /* F3 or CMD/CTRL + F */
+ if (70 === e.keyCode && document.activeElement === searchInput) {
+ /*
+ * If CMD/CTRL + F is hit while having focus on search input,
+ * the user probably meant to trigger browser search instead.
+ * Let the browser execute its behavior:
+ */
+ return;
+ }
+
+ e.preventDefault();
+ search.className = search.className.replace(/\bsf-dump-search-hidden\b/, '');
+ searchInput.focus();
+ } else if (isSearchActive) {
+ if (27 === e.keyCode) {
+ /* ESC key */
+ search.className += ' sf-dump-search-hidden';
+ e.preventDefault();
+ resetHighlightedNodes(root);
+ searchInput.value = '';
+ } else if (
+ (isCtrlKey(e) && 71 === e.keyCode) /* CMD/CTRL + G */
+ || 13 === e.keyCode /* Enter */
+ || 114 === e.keyCode /* F3 */
+ ) {
+ e.preventDefault();
+ e.shiftKey ? state.previous() : state.next();
+ collapseAll(root);
+ showCurrent(state);
+ }
+ }
+ });
+ }
+
+ if (0 >= options.maxStringLength) {
+ return;
+ }
+ try {
+ elt = root.querySelectorAll('.sf-dump-str');
+ len = elt.length;
+ i = 0;
+ t = [];
+
+ while (i < len) t.push(elt[i++]);
+ len = t.length;
+
+ for (i = 0; i < len; ++i) {
+ elt = t[i];
+ s = elt.innerText || elt.textContent;
+ x = s.length - options.maxStringLength;
+ if (0 < x) {
+ h = elt.innerHTML;
+ elt[elt.innerText ? 'innerText' : 'textContent'] = s.substring(0, options.maxStringLength);
+ elt.className += ' sf-dump-str-collapse';
+ elt.innerHTML = '<span class=sf-dump-str-collapse>'+h+'<a class="sf-dump-ref sf-dump-str-toggle" title="Collapse"> ◀</a></span>'+
+ '<span class=sf-dump-str-expand>'+elt.innerHTML+'<a class="sf-dump-ref sf-dump-str-toggle" title="'+x+' remaining characters"> ▶</a></span>';
+ }
+ }
+ } catch (e) {
+ }
+};
+
+})(document);
+</script><style>
+pre.sf-dump {
+ display: block;
+ white-space: pre;
+ padding: 5px;
+ overflow: initial !important;
+}
+pre.sf-dump:after {
+ content: "";
+ visibility: hidden;
+ display: block;
+ height: 0;
+ clear: both;
+}
+pre.sf-dump span {
+ display: inline;
+}
+pre.sf-dump a {
+ text-decoration: none;
+ cursor: pointer;
+ border: 0;
+ outline: none;
+ color: inherit;
+}
+pre.sf-dump img {
+ max-width: 50em;
+ max-height: 50em;
+ margin: .5em 0 0 0;
+ padding: 0;
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAHUlEQVQY02O8zAABilCaiQEN0EeA8QuUcX9g3QEAAjcC5piyhyEAAAAASUVORK5CYII=) #D3D3D3;
+}
+pre.sf-dump .sf-dump-ellipsis {
+ display: inline-block;
+ overflow: visible;
+ text-overflow: ellipsis;
+ max-width: 5em;
+ white-space: nowrap;
+ overflow: hidden;
+ vertical-align: top;
+}
+pre.sf-dump .sf-dump-ellipsis+.sf-dump-ellipsis {
+ max-width: none;
+}
+pre.sf-dump code {
+ display:inline;
+ padding:0;
+ background:none;
+}
+.sf-dump-public.sf-dump-highlight,
+.sf-dump-protected.sf-dump-highlight,
+.sf-dump-private.sf-dump-highlight,
+.sf-dump-str.sf-dump-highlight,
+.sf-dump-key.sf-dump-highlight {
+ background: rgba(111, 172, 204, 0.3);
+ border: 1px solid #7DA0B1;
+ border-radius: 3px;
+}
+.sf-dump-public.sf-dump-highlight-active,
+.sf-dump-protected.sf-dump-highlight-active,
+.sf-dump-private.sf-dump-highlight-active,
+.sf-dump-str.sf-dump-highlight-active,
+.sf-dump-key.sf-dump-highlight-active {
+ background: rgba(253, 175, 0, 0.4);
+ border: 1px solid #ffa500;
+ border-radius: 3px;
+}
+pre.sf-dump .sf-dump-search-hidden {
+ display: none !important;
+}
+pre.sf-dump .sf-dump-search-wrapper {
+ font-size: 0;
+ white-space: nowrap;
+ margin-bottom: 5px;
+ display: flex;
+ position: -webkit-sticky;
+ position: sticky;
+ top: 5px;
+}
+pre.sf-dump .sf-dump-search-wrapper > * {
+ vertical-align: top;
+ box-sizing: border-box;
+ height: 21px;
+ font-weight: normal;
+ border-radius: 0;
+ background: #FFF;
+ color: #757575;
+ border: 1px solid #BBB;
+}
+pre.sf-dump .sf-dump-search-wrapper > input.sf-dump-search-input {
+ padding: 3px;
+ height: 21px;
+ font-size: 12px;
+ border-right: none;
+ border-top-left-radius: 3px;
+ border-bottom-left-radius: 3px;
+ color: #000;
+ min-width: 15px;
+ width: 100%;
+}
+pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next,
+pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous {
+ background: #F2F2F2;
+ outline: none;
+ border-left: none;
+ font-size: 0;
+ line-height: 0;
+}
+pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next {
+ border-top-right-radius: 3px;
+ border-bottom-right-radius: 3px;
+}
+pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next > svg,
+pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous > svg {
+ pointer-events: none;
+ width: 12px;
+ height: 12px;
+}
+pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-count {
+ display: inline-block;
+ padding: 0 5px;
+ margin: 0;
+ border-left: none;
+ line-height: 21px;
+ font-size: 12px;
+}
+EOHTML
+ );
+
+ foreach ($this->styles as $class => $style) {
+ $line .= 'pre.sf-dump'.('default' === $class ? ', pre.sf-dump' : '').' .sf-dump-'.$class.'{'.$style.'}';
+ }
+ $line .= 'pre.sf-dump .sf-dump-ellipsis-note{'.$this->styles['note'].'}';
+
+ return $this->dumpHeader = preg_replace('/\s+/', ' ', $line).'</style>'.$this->dumpHeader;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut)
+ {
+ if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) {
+ $this->dumpKey($cursor);
+ $this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []);
+ $this->line .= $cursor->depth >= $this->displayOptions['maxDepth'] ? ' <samp class=sf-dump-compact>' : ' <samp class=sf-dump-expanded>';
+ $this->endValue($cursor);
+ $this->line .= $this->indentPad;
+ $this->line .= sprintf('<img src="data:%s;base64,%s" /></samp>', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data']));
+ $this->endValue($cursor);
+ } else {
+ parent::dumpString($cursor, $str, $bin, $cut);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild)
+ {
+ if (Cursor::HASH_OBJECT === $type) {
+ $cursor->attr['depth'] = $cursor->depth;
+ }
+ parent::enterHash($cursor, $type, $class, false);
+
+ if ($cursor->skipChildren || $cursor->depth >= $this->displayOptions['maxDepth']) {
+ $cursor->skipChildren = false;
+ $eol = ' class=sf-dump-compact>';
+ } else {
+ $this->expandNextHash = false;
+ $eol = ' class=sf-dump-expanded>';
+ }
+
+ if ($hasChild) {
+ $this->line .= '<samp data-depth='.($cursor->depth + 1);
+ if ($cursor->refIndex) {
+ $r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2;
+ $r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex;
+
+ $this->line .= sprintf(' id=%s-ref%s', $this->dumpId, $r);
+ }
+ $this->line .= $eol;
+ $this->dumpLine($cursor->depth);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut)
+ {
+ $this->dumpEllipsis($cursor, $hasChild, $cut);
+ if ($hasChild) {
+ $this->line .= '</samp>';
+ }
+ parent::leaveHash($cursor, $type, $class, $hasChild, 0);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function style(string $style, string $value, array $attr = [])
+ {
+ if ('' === $value) {
+ return '';
+ }
+
+ $v = esc($value);
+
+ if ('ref' === $style) {
+ if (empty($attr['count'])) {
+ return sprintf('<a class=sf-dump-ref>%s</a>', $v);
+ }
+ $r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2).substr($value, 1);
+
+ return sprintf('<a class=sf-dump-ref href=#%s-ref%s title="%d occurrences">%s</a>', $this->dumpId, $r, 1 + $attr['count'], $v);
+ }
+
+ if ('const' === $style && isset($attr['value'])) {
+ $style .= sprintf(' title="%s"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value'])));
+ } elseif ('public' === $style) {
+ $style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property');
+ } elseif ('str' === $style && 1 < $attr['length']) {
+ $style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : '');
+ } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && false !== $c = strrpos($value, '\\')) {
+ $style .= ' title=""';
+ $attr += [
+ 'ellipsis' => \strlen($value) - $c,
+ 'ellipsis-type' => 'note',
+ 'ellipsis-tail' => 1,
+ ];
+ } elseif ('protected' === $style) {
+ $style .= ' title="Protected property"';
+ } elseif ('meta' === $style && isset($attr['title'])) {
+ $style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title'])));
+ } elseif ('private' === $style) {
+ $style .= sprintf(' title="Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class'])));
+ }
+ $map = static::$controlCharsMap;
+
+ if (isset($attr['ellipsis'])) {
+ $class = 'sf-dump-ellipsis';
+ if (isset($attr['ellipsis-type'])) {
+ $class = sprintf('"%s sf-dump-ellipsis-%s"', $class, $attr['ellipsis-type']);
+ }
+ $label = esc(substr($value, -$attr['ellipsis']));
+ $style = str_replace(' title="', " title=\"$v\n", $style);
+ $v = sprintf('<span class=%s>%s</span>', $class, substr($v, 0, -\strlen($label)));
+
+ if (!empty($attr['ellipsis-tail'])) {
+ $tail = \strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail'])));
+ $v .= sprintf('<span class=%s>%s</span>%s', $class, substr($label, 0, $tail), substr($label, $tail));
+ } else {
+ $v .= $label;
+ }
+ }
+
+ $v = "<span class=sf-dump-{$style}>".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) {
+ $s = $b = '<span class="sf-dump-default';
+ $c = $c[$i = 0];
+ if ($ns = "\r" === $c[$i] || "\n" === $c[$i]) {
+ $s .= ' sf-dump-ns';
+ }
+ $s .= '">';
+ do {
+ if (("\r" === $c[$i] || "\n" === $c[$i]) !== $ns) {
+ $s .= '</span>'.$b;
+ if ($ns = !$ns) {
+ $s .= ' sf-dump-ns';
+ }
+ $s .= '">';
+ }
+
+ $s .= $map[$c[$i]] ?? sprintf('\x%02X', \ord($c[$i]));
+ } while (isset($c[++$i]));
+
+ return $s.'</span>';
+ }, $v).'</span>';
+
+ if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) {
+ $attr['href'] = $href;
+ }
+ if (isset($attr['href'])) {
+ $target = isset($attr['file']) ? '' : ' target="_blank"';
+ $v = sprintf('<a href="%s"%s rel="noopener noreferrer">%s</a>', esc($this->utf8Encode($attr['href'])), $target, $v);
+ }
+ if (isset($attr['lang'])) {
+ $v = sprintf('<code class="%s">%s</code>', esc($attr['lang']), $v);
+ }
+
+ return $v;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function dumpLine(int $depth, bool $endOfValue = false)
+ {
+ if (-1 === $this->lastDepth) {
+ $this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line;
+ }
+ if ($this->headerIsDumped !== ($this->outputStream ?? $this->lineDumper)) {
+ $this->line = $this->getDumpHeader().$this->line;
+ }
+
+ if (-1 === $depth) {
+ $args = ['"'.$this->dumpId.'"'];
+ if ($this->extraDisplayOptions) {
+ $args[] = json_encode($this->extraDisplayOptions, \JSON_FORCE_OBJECT);
+ }
+ // Replace is for BC
+ $this->line .= sprintf(str_replace('"%s"', '%s', $this->dumpSuffix), implode(', ', $args));
+ }
+ $this->lastDepth = $depth;
+
+ $this->line = mb_convert_encoding($this->line, 'HTML-ENTITIES', 'UTF-8');
+
+ if (-1 === $depth) {
+ AbstractDumper::dumpLine(0);
+ }
+ AbstractDumper::dumpLine($depth);
+ }
+
+ private function getSourceLink(string $file, int $line)
+ {
+ $options = $this->extraDisplayOptions + $this->displayOptions;
+
+ if ($fmt = $options['fileLinkFormat']) {
+ return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line);
+ }
+
+ return false;
+ }
+}
+
+function esc(string $str)
+{
+ return htmlspecialchars($str, \ENT_QUOTES, 'UTF-8');
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ServerDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ServerDumper.php
new file mode 100644
index 0000000..94795bf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ServerDumper.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Dumper;
+
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
+use Symfony\Component\VarDumper\Server\Connection;
+
+/**
+ * ServerDumper forwards serialized Data clones to a server.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+class ServerDumper implements DataDumperInterface
+{
+ private $connection;
+ private $wrappedDumper;
+
+ /**
+ * @param string $host The server host
+ * @param DataDumperInterface|null $wrappedDumper A wrapped instance used whenever we failed contacting the server
+ * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name
+ */
+ public function __construct(string $host, DataDumperInterface $wrappedDumper = null, array $contextProviders = [])
+ {
+ $this->connection = new Connection($host, $contextProviders);
+ $this->wrappedDumper = $wrappedDumper;
+ }
+
+ public function getContextProviders(): array
+ {
+ return $this->connection->getContextProviders();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dump(Data $data)
+ {
+ if (!$this->connection->write($data) && $this->wrappedDumper) {
+ $this->wrappedDumper->dump($data);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php
new file mode 100644
index 0000000..122f0d3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Exception;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ThrowingCasterException extends \Exception
+{
+ /**
+ * @param \Throwable $prev The exception thrown from the caster
+ */
+ public function __construct(\Throwable $prev)
+ {
+ parent::__construct('Unexpected '.\get_class($prev).' thrown from a caster: '.$prev->getMessage(), 0, $prev);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/LICENSE
new file mode 100644
index 0000000..c1f0aac
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014-2021 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/README.md
new file mode 100644
index 0000000..bdac244
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/README.md
@@ -0,0 +1,15 @@
+VarDumper Component
+===================
+
+The VarDumper component provides mechanisms for walking through any arbitrary
+PHP variable. It provides a better `dump()` function that you can use instead
+of `var_dump`.
+
+Resources
+---------
+
+ * [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/bin/var-dump-server b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/bin/var-dump-server
new file mode 100755
index 0000000..98c813a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/bin/var-dump-server
@@ -0,0 +1,63 @@
+#!/usr/bin/env php
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Starts a dump server to collect and output dumps on a single place with multiple formats support.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Input\ArgvInput;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Logger\ConsoleLogger;
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Symfony\Component\VarDumper\Command\ServerDumpCommand;
+use Symfony\Component\VarDumper\Server\DumpServer;
+
+function includeIfExists(string $file): bool
+{
+ return file_exists($file) && include $file;
+}
+
+if (
+ !includeIfExists(__DIR__ . '/../../../../autoload.php') &&
+ !includeIfExists(__DIR__ . '/../../vendor/autoload.php') &&
+ !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php')
+) {
+ fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL);
+ exit(1);
+}
+
+if (!class_exists(Application::class)) {
+ fwrite(STDERR, 'You need the "symfony/console" component in order to run the VarDumper server.'.PHP_EOL);
+ exit(1);
+}
+
+$input = new ArgvInput();
+$output = new ConsoleOutput();
+$defaultHost = '127.0.0.1:9912';
+$host = $input->getParameterOption(['--host'], $_SERVER['VAR_DUMPER_SERVER'] ?? $defaultHost, true);
+$logger = interface_exists(LoggerInterface::class) ? new ConsoleLogger($output->getErrorOutput()) : null;
+
+$app = new Application();
+
+$app->getDefinition()->addOption(
+ new InputOption('--host', null, InputOption::VALUE_REQUIRED, 'The address the server should listen to', $defaultHost)
+);
+
+$app->add($command = new ServerDumpCommand(new DumpServer($host, $logger)))
+ ->getApplication()
+ ->setDefaultCommand($command->getName(), true)
+ ->run($input, $output)
+;
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css
new file mode 100644
index 0000000..8f706d6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css
@@ -0,0 +1,130 @@
+body {
+ display: flex;
+ flex-direction: column-reverse;
+ justify-content: flex-end;
+ max-width: 1140px;
+ margin: auto;
+ padding: 15px;
+ word-wrap: break-word;
+ background-color: #F9F9F9;
+ color: #222;
+ font-family: Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ line-height: 1.4;
+}
+p {
+ margin: 0;
+}
+a {
+ color: #218BC3;
+ text-decoration: none;
+}
+a:hover {
+ text-decoration: underline;
+}
+.text-small {
+ font-size: 12px !important;
+}
+article {
+ margin: 5px;
+ margin-bottom: 10px;
+}
+article > header > .row {
+ display: flex;
+ flex-direction: row;
+ align-items: baseline;
+ margin-bottom: 10px;
+}
+article > header > .row > .col {
+ flex: 1;
+ display: flex;
+ align-items: baseline;
+}
+article > header > .row > h2 {
+ font-size: 14px;
+ color: #222;
+ font-weight: normal;
+ font-family: "Lucida Console", monospace, sans-serif;
+ word-break: break-all;
+ margin: 20px 5px 0 0;
+ user-select: all;
+}
+article > header > .row > h2 > code {
+ white-space: nowrap;
+ user-select: none;
+ color: #cc2255;
+ background-color: #f7f7f9;
+ border: 1px solid #e1e1e8;
+ border-radius: 3px;
+ margin-right: 5px;
+ padding: 0 3px;
+}
+article > header > .row > time.col {
+ flex: 0;
+ text-align: right;
+ white-space: nowrap;
+ color: #999;
+ font-style: italic;
+}
+article > header ul.tags {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ font-size: 12px;
+}
+article > header ul.tags > li {
+ user-select: all;
+ margin-bottom: 2px;
+}
+article > header ul.tags > li > span.badge {
+ display: inline-block;
+ padding: .25em .4em;
+ margin-right: 5px;
+ border-radius: 4px;
+ background-color: #6c757d3b;
+ color: #524d4d;
+ font-size: 12px;
+ text-align: center;
+ font-weight: 700;
+ line-height: 1;
+ white-space: nowrap;
+ vertical-align: baseline;
+ user-select: none;
+}
+article > section.body {
+ border: 1px solid #d8d8d8;
+ background: #FFF;
+ padding: 10px;
+ border-radius: 3px;
+}
+pre.sf-dump {
+ border-radius: 3px;
+ margin-bottom: 0;
+}
+.hidden {
+ display: none !important;
+}
+.dumped-tag > .sf-dump {
+ display: inline-block;
+ margin: 0;
+ padding: 1px 5px;
+ line-height: 1.4;
+ vertical-align: top;
+ background-color: transparent;
+ user-select: auto;
+}
+.dumped-tag > pre.sf-dump,
+.dumped-tag > .sf-dump-default {
+ color: #CC7832;
+ background: none;
+}
+.dumped-tag > .sf-dump .sf-dump-str { color: #629755; }
+.dumped-tag > .sf-dump .sf-dump-private,
+.dumped-tag > .sf-dump .sf-dump-protected,
+.dumped-tag > .sf-dump .sf-dump-public { color: #262626; }
+.dumped-tag > .sf-dump .sf-dump-note { color: #6897BB; }
+.dumped-tag > .sf-dump .sf-dump-key { color: #789339; }
+.dumped-tag > .sf-dump .sf-dump-ref { color: #6E6E6E; }
+.dumped-tag > .sf-dump .sf-dump-ellipsis { color: #CC7832; max-width: 100em; }
+.dumped-tag > .sf-dump .sf-dump-ellipsis-path { max-width: 5em; }
+.dumped-tag > .sf-dump .sf-dump-ns { user-select: none; }
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/functions/dump.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/functions/dump.php
new file mode 100644
index 0000000..a485d57
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/functions/dump.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Component\VarDumper\VarDumper;
+
+if (!function_exists('dump')) {
+ /**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+ function dump($var, ...$moreVars)
+ {
+ VarDumper::dump($var);
+
+ foreach ($moreVars as $v) {
+ VarDumper::dump($v);
+ }
+
+ if (1 < func_num_args()) {
+ return func_get_args();
+ }
+
+ return $var;
+ }
+}
+
+if (!function_exists('dd')) {
+ function dd(...$vars)
+ {
+ foreach ($vars as $v) {
+ VarDumper::dump($v);
+ }
+
+ exit(1);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js
new file mode 100644
index 0000000..63101e5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js
@@ -0,0 +1,10 @@
+document.addEventListener('DOMContentLoaded', function() {
+ let prev = null;
+ Array.from(document.getElementsByTagName('article')).reverse().forEach(function (article) {
+ const dedupId = article.dataset.dedupId;
+ if (dedupId === prev) {
+ article.getElementsByTagName('header')[0].classList.add('hidden');
+ }
+ prev = dedupId;
+ });
+});
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Server/Connection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Server/Connection.php
new file mode 100644
index 0000000..55d9214
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Server/Connection.php
@@ -0,0 +1,95 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Server;
+
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
+
+/**
+ * Forwards serialized Data clones to a server.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+class Connection
+{
+ private $host;
+ private $contextProviders;
+ private $socket;
+
+ /**
+ * @param string $host The server host
+ * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name
+ */
+ public function __construct(string $host, array $contextProviders = [])
+ {
+ if (!str_contains($host, '://')) {
+ $host = 'tcp://'.$host;
+ }
+
+ $this->host = $host;
+ $this->contextProviders = $contextProviders;
+ }
+
+ public function getContextProviders(): array
+ {
+ return $this->contextProviders;
+ }
+
+ public function write(Data $data): bool
+ {
+ $socketIsFresh = !$this->socket;
+ if (!$this->socket = $this->socket ?: $this->createSocket()) {
+ return false;
+ }
+
+ $context = ['timestamp' => microtime(true)];
+ foreach ($this->contextProviders as $name => $provider) {
+ $context[$name] = $provider->getContext();
+ }
+ $context = array_filter($context);
+ $encodedPayload = base64_encode(serialize([$data, $context]))."\n";
+
+ set_error_handler([self::class, 'nullErrorHandler']);
+ try {
+ if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {
+ return true;
+ }
+ if (!$socketIsFresh) {
+ stream_socket_shutdown($this->socket, \STREAM_SHUT_RDWR);
+ fclose($this->socket);
+ $this->socket = $this->createSocket();
+ }
+ if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {
+ return true;
+ }
+ } finally {
+ restore_error_handler();
+ }
+
+ return false;
+ }
+
+ private static function nullErrorHandler(int $t, string $m)
+ {
+ // no-op
+ }
+
+ private function createSocket()
+ {
+ set_error_handler([self::class, 'nullErrorHandler']);
+ try {
+ return stream_socket_client($this->host, $errno, $errstr, 3, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT);
+ } finally {
+ restore_error_handler();
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Server/DumpServer.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Server/DumpServer.php
new file mode 100644
index 0000000..7cb5bf0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Server/DumpServer.php
@@ -0,0 +1,111 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Server;
+
+use Psr\Log\LoggerInterface;
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Cloner\Stub;
+
+/**
+ * A server collecting Data clones sent by a ServerDumper.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ *
+ * @final
+ */
+class DumpServer
+{
+ private $host;
+ private $socket;
+ private $logger;
+
+ public function __construct(string $host, LoggerInterface $logger = null)
+ {
+ if (!str_contains($host, '://')) {
+ $host = 'tcp://'.$host;
+ }
+
+ $this->host = $host;
+ $this->logger = $logger;
+ }
+
+ public function start(): void
+ {
+ if (!$this->socket = stream_socket_server($this->host, $errno, $errstr)) {
+ throw new \RuntimeException(sprintf('Server start failed on "%s": ', $this->host).$errstr.' '.$errno);
+ }
+ }
+
+ public function listen(callable $callback): void
+ {
+ if (null === $this->socket) {
+ $this->start();
+ }
+
+ foreach ($this->getMessages() as $clientId => $message) {
+ if ($this->logger) {
+ $this->logger->info('Received a payload from client {clientId}', ['clientId' => $clientId]);
+ }
+
+ $payload = @unserialize(base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]);
+
+ // Impossible to decode the message, give up.
+ if (false === $payload) {
+ if ($this->logger) {
+ $this->logger->warning('Unable to decode a message from {clientId} client.', ['clientId' => $clientId]);
+ }
+
+ continue;
+ }
+
+ if (!\is_array($payload) || \count($payload) < 2 || !$payload[0] instanceof Data || !\is_array($payload[1])) {
+ if ($this->logger) {
+ $this->logger->warning('Invalid payload from {clientId} client. Expected an array of two elements (Data $data, array $context)', ['clientId' => $clientId]);
+ }
+
+ continue;
+ }
+
+ [$data, $context] = $payload;
+
+ $callback($data, $context, $clientId);
+ }
+ }
+
+ public function getHost(): string
+ {
+ return $this->host;
+ }
+
+ private function getMessages(): iterable
+ {
+ $sockets = [(int) $this->socket => $this->socket];
+ $write = [];
+
+ while (true) {
+ $read = $sockets;
+ stream_select($read, $write, $write, null);
+
+ foreach ($read as $stream) {
+ if ($this->socket === $stream) {
+ $stream = stream_socket_accept($this->socket);
+ $sockets[(int) $stream] = $stream;
+ } elseif (feof($stream)) {
+ unset($sockets[(int) $stream]);
+ fclose($stream);
+ } else {
+ yield (int) $stream => fgets($stream);
+ }
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php
new file mode 100644
index 0000000..33d60c0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php
@@ -0,0 +1,84 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Test;
+
+use Symfony\Component\VarDumper\Cloner\VarCloner;
+use Symfony\Component\VarDumper\Dumper\CliDumper;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+trait VarDumperTestTrait
+{
+ /**
+ * @internal
+ */
+ private $varDumperConfig = [
+ 'casters' => [],
+ 'flags' => null,
+ ];
+
+ protected function setUpVarDumper(array $casters, int $flags = null): void
+ {
+ $this->varDumperConfig['casters'] = $casters;
+ $this->varDumperConfig['flags'] = $flags;
+ }
+
+ /**
+ * @after
+ */
+ protected function tearDownVarDumper(): void
+ {
+ $this->varDumperConfig['casters'] = [];
+ $this->varDumperConfig['flags'] = null;
+ }
+
+ public function assertDumpEquals($expected, $data, int $filter = 0, string $message = '')
+ {
+ $this->assertSame($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message);
+ }
+
+ public function assertDumpMatchesFormat($expected, $data, int $filter = 0, string $message = '')
+ {
+ $this->assertStringMatchesFormat($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message);
+ }
+
+ protected function getDump($data, $key = null, int $filter = 0): ?string
+ {
+ if (null === $flags = $this->varDumperConfig['flags']) {
+ $flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0;
+ $flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0;
+ $flags |= getenv('DUMP_COMMA_SEPARATOR') ? CliDumper::DUMP_COMMA_SEPARATOR : 0;
+ }
+
+ $cloner = new VarCloner();
+ $cloner->addCasters($this->varDumperConfig['casters']);
+ $cloner->setMaxItems(-1);
+ $dumper = new CliDumper(null, null, $flags);
+ $dumper->setColors(false);
+ $data = $cloner->cloneVar($data, $filter)->withRefHandles(false);
+ if (null !== $key && null === $data = $data->seek($key)) {
+ return null;
+ }
+
+ return rtrim($dumper->dump($data, true));
+ }
+
+ private function prepareExpectation($expected, int $filter): string
+ {
+ if (!\is_string($expected)) {
+ $expected = $this->getDump($expected, null, $filter);
+ }
+
+ return rtrim($expected);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/VarDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/VarDumper.php
new file mode 100644
index 0000000..b223e06
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/VarDumper.php
@@ -0,0 +1,109 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
+use Symfony\Component\VarDumper\Caster\ReflectionCaster;
+use Symfony\Component\VarDumper\Cloner\VarCloner;
+use Symfony\Component\VarDumper\Dumper\CliDumper;
+use Symfony\Component\VarDumper\Dumper\ContextProvider\CliContextProvider;
+use Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider;
+use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
+use Symfony\Component\VarDumper\Dumper\ContextualizedDumper;
+use Symfony\Component\VarDumper\Dumper\HtmlDumper;
+use Symfony\Component\VarDumper\Dumper\ServerDumper;
+
+// Load the global dump() function
+require_once __DIR__.'/Resources/functions/dump.php';
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class VarDumper
+{
+ private static $handler;
+
+ public static function dump($var)
+ {
+ if (null === self::$handler) {
+ self::register();
+ }
+
+ return (self::$handler)($var);
+ }
+
+ public static function setHandler(callable $callable = null)
+ {
+ $prevHandler = self::$handler;
+
+ // Prevent replacing the handler with expected format as soon as the env var was set:
+ if (isset($_SERVER['VAR_DUMPER_FORMAT'])) {
+ return $prevHandler;
+ }
+
+ self::$handler = $callable;
+
+ return $prevHandler;
+ }
+
+ private static function register(): void
+ {
+ $cloner = new VarCloner();
+ $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);
+
+ $format = $_SERVER['VAR_DUMPER_FORMAT'] ?? null;
+ switch (true) {
+ case 'html' === $format:
+ $dumper = new HtmlDumper();
+ break;
+ case 'cli' === $format:
+ $dumper = new CliDumper();
+ break;
+ case 'server' === $format:
+ case $format && 'tcp' === parse_url($format, \PHP_URL_SCHEME):
+ $host = 'server' === $format ? $_SERVER['VAR_DUMPER_SERVER'] ?? '127.0.0.1:9912' : $format;
+ $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper();
+ $dumper = new ServerDumper($host, $dumper, self::getDefaultContextProviders());
+ break;
+ default:
+ $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper();
+ }
+
+ if (!$dumper instanceof ServerDumper) {
+ $dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]);
+ }
+
+ self::$handler = function ($var) use ($cloner, $dumper) {
+ $dumper->dump($cloner->cloneVar($var));
+ };
+ }
+
+ private static function getDefaultContextProviders(): array
+ {
+ $contextProviders = [];
+
+ if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && (class_exists(Request::class))) {
+ $requestStack = new RequestStack();
+ $requestStack->push(Request::createFromGlobals());
+ $contextProviders['request'] = new RequestContextProvider($requestStack);
+ }
+
+ $fileLinkFormatter = class_exists(FileLinkFormatter::class) ? new FileLinkFormatter(null, $requestStack ?? null) : null;
+
+ return $contextProviders + [
+ 'cli' => new CliContextProvider(),
+ 'source' => new SourceContextProvider(null, null, $fileLinkFormatter),
+ ];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/composer.json
new file mode 100644
index 0000000..2d4889d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/var-dumper/composer.json
@@ -0,0 +1,49 @@
+{
+ "name": "symfony/var-dumper",
+ "type": "library",
+ "description": "Provides mechanisms for walking through any arbitrary PHP variable",
+ "keywords": ["dump", "debug"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "require-dev": {
+ "ext-iconv": "*",
+ "symfony/console": "^4.4|^5.0",
+ "symfony/process": "^4.4|^5.0",
+ "twig/twig": "^2.13|^3.0.4"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<5.4.3",
+ "symfony/console": "<4.4"
+ },
+ "suggest": {
+ "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
+ "ext-intl": "To show region name in time zone dump",
+ "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
+ },
+ "autoload": {
+ "files": [ "Resources/functions/dump.php" ],
+ "psr-4": { "Symfony\\Component\\VarDumper\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "bin": [
+ "Resources/bin/var-dump-server"
+ ],
+ "minimum-stability": "dev"
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/.github/workflows/run-tests.yml b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/.github/workflows/run-tests.yml
new file mode 100644
index 0000000..c4f275b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/.github/workflows/run-tests.yml
@@ -0,0 +1,38 @@
+name: Run tests
+
+on: [push, pull_request]
+
+jobs:
+ tests:
+ strategy:
+ matrix:
+ os: [Ubuntu, macOS]
+ php: [7.2, 7.3, 7.4, 8.0]
+
+ include:
+ - os: Ubuntu
+ os-version: ubuntu-latest
+
+ - os: macOS
+ os-version: macos-latest
+
+ name: ${{ matrix.os }} - PHP ${{ matrix.php }}
+
+ runs-on: ${{ matrix.os-version }}
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v1
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ extensions: posix, dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick
+ coverage: none
+
+ - name: Install dependencies
+ run: composer update --prefer-stable --prefer-dist --no-interaction
+
+ - name: Run tests
+ run: bash upgrade.sh
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/composer.json
new file mode 100644
index 0000000..58e5f6c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/composer.json
@@ -0,0 +1,47 @@
+{
+ "name": "tightenco/collect",
+ "description": "Collect - Illuminate Collections as a separate package.",
+ "keywords": ["laravel", "collection"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylorotwell@gmail.com"
+ }
+ ],
+ "require": {
+ "php": "^7.2|^8.0",
+ "symfony/var-dumper": "^3.4 || ^4.0 || ^5.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.0",
+ "phpunit/phpunit": "^8.3",
+ "nesbot/carbon": "^2.23.0"
+ },
+ "autoload": {
+ "files": [
+ "src/Collect/Support/helpers.php",
+ "src/Collect/Support/alias.php"
+ ],
+ "psr-4": {
+ "Tightenco\\Collect\\": "src/Collect"
+ }
+ },
+ "autoload-dev": {
+ "files": [
+ "tests/files/Support/Carbon.php",
+ "tests/files/Support/HtmlString.php",
+ "tests/files/Support/HigherOrderTapProxy.php",
+ "tests/files/Support/Str.php",
+ "tests/files/Support/Stringable.php"
+ ]
+ },
+ "scripts": {
+ "test": [
+ "@composer install",
+ "phpunit"
+ ]
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Contracts/Support/Arrayable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Contracts/Support/Arrayable.php
new file mode 100755
index 0000000..a205804
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Contracts/Support/Arrayable.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Tightenco\Collect\Contracts\Support;
+
+interface Arrayable
+{
+ /**
+ * Get the instance as an array.
+ *
+ * @return array
+ */
+ public function toArray();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Contracts/Support/Htmlable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Contracts/Support/Htmlable.php
new file mode 100644
index 0000000..aa20e96
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Contracts/Support/Htmlable.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Tightenco\Collect\Contracts\Support;
+
+interface Htmlable
+{
+ /**
+ * Get content as a string of HTML.
+ *
+ * @return string
+ */
+ public function toHtml();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Contracts/Support/Jsonable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Contracts/Support/Jsonable.php
new file mode 100755
index 0000000..6b73730
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Contracts/Support/Jsonable.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Tightenco\Collect\Contracts\Support;
+
+interface Jsonable
+{
+ /**
+ * Convert the object to its JSON representation.
+ *
+ * @param int $options
+ * @return string
+ */
+ public function toJson($options = 0);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Arr.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Arr.php
new file mode 100644
index 0000000..b99db01
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Arr.php
@@ -0,0 +1,681 @@
+<?php
+
+namespace Tightenco\Collect\Support;
+
+use ArrayAccess;
+use Tightenco\Collect\Support\Traits\Macroable;
+use InvalidArgumentException;
+
+class Arr
+{
+ use Macroable;
+
+ /**
+ * Determine whether the given value is array accessible.
+ *
+ * @param mixed $value
+ * @return bool
+ */
+ public static function accessible($value)
+ {
+ return is_array($value) || $value instanceof ArrayAccess;
+ }
+
+ /**
+ * Add an element to an array using "dot" notation if it doesn't exist.
+ *
+ * @param array $array
+ * @param string $key
+ * @param mixed $value
+ * @return array
+ */
+ public static function add($array, $key, $value)
+ {
+ if (is_null(static::get($array, $key))) {
+ static::set($array, $key, $value);
+ }
+
+ return $array;
+ }
+
+ /**
+ * Collapse an array of arrays into a single array.
+ *
+ * @param iterable $array
+ * @return array
+ */
+ public static function collapse($array)
+ {
+ $results = [];
+
+ foreach ($array as $values) {
+ if ($values instanceof Collection) {
+ $values = $values->all();
+ } elseif (! is_array($values)) {
+ continue;
+ }
+
+ $results[] = $values;
+ }
+
+ return array_merge([], ...$results);
+ }
+
+ /**
+ * Cross join the given arrays, returning all possible permutations.
+ *
+ * @param iterable ...$arrays
+ * @return array
+ */
+ public static function crossJoin(...$arrays)
+ {
+ $results = [[]];
+
+ foreach ($arrays as $index => $array) {
+ $append = [];
+
+ foreach ($results as $product) {
+ foreach ($array as $item) {
+ $product[$index] = $item;
+
+ $append[] = $product;
+ }
+ }
+
+ $results = $append;
+ }
+
+ return $results;
+ }
+
+ /**
+ * Divide an array into two arrays. One with keys and the other with values.
+ *
+ * @param array $array
+ * @return array
+ */
+ public static function divide($array)
+ {
+ return [array_keys($array), array_values($array)];
+ }
+
+ /**
+ * Flatten a multi-dimensional associative array with dots.
+ *
+ * @param iterable $array
+ * @param string $prepend
+ * @return array
+ */
+ public static function dot($array, $prepend = '')
+ {
+ $results = [];
+
+ foreach ($array as $key => $value) {
+ if (is_array($value) && ! empty($value)) {
+ $results = array_merge($results, static::dot($value, $prepend.$key.'.'));
+ } else {
+ $results[$prepend.$key] = $value;
+ }
+ }
+
+ return $results;
+ }
+
+ /**
+ * Get all of the given array except for a specified array of keys.
+ *
+ * @param array $array
+ * @param array|string $keys
+ * @return array
+ */
+ public static function except($array, $keys)
+ {
+ static::forget($array, $keys);
+
+ return $array;
+ }
+
+ /**
+ * Determine if the given key exists in the provided array.
+ *
+ * @param \ArrayAccess|array $array
+ * @param string|int $key
+ * @return bool
+ */
+ public static function exists($array, $key)
+ {
+ if ($array instanceof Enumerable) {
+ return $array->has($key);
+ }
+
+ if ($array instanceof ArrayAccess) {
+ return $array->offsetExists($key);
+ }
+
+ return array_key_exists($key, $array);
+ }
+
+ /**
+ * Return the first element in an array passing a given truth test.
+ *
+ * @param iterable $array
+ * @param callable|null $callback
+ * @param mixed $default
+ * @return mixed
+ */
+ public static function first($array, callable $callback = null, $default = null)
+ {
+ if (is_null($callback)) {
+ if (empty($array)) {
+ return value($default);
+ }
+
+ foreach ($array as $item) {
+ return $item;
+ }
+ }
+
+ foreach ($array as $key => $value) {
+ if ($callback($value, $key)) {
+ return $value;
+ }
+ }
+
+ return value($default);
+ }
+
+ /**
+ * Return the last element in an array passing a given truth test.
+ *
+ * @param array $array
+ * @param callable|null $callback
+ * @param mixed $default
+ * @return mixed
+ */
+ public static function last($array, callable $callback = null, $default = null)
+ {
+ if (is_null($callback)) {
+ return empty($array) ? value($default) : end($array);
+ }
+
+ return static::first(array_reverse($array, true), $callback, $default);
+ }
+
+ /**
+ * Flatten a multi-dimensional array into a single level.
+ *
+ * @param iterable $array
+ * @param int $depth
+ * @return array
+ */
+ public static function flatten($array, $depth = INF)
+ {
+ $result = [];
+
+ foreach ($array as $item) {
+ $item = $item instanceof Collection ? $item->all() : $item;
+
+ if (! is_array($item)) {
+ $result[] = $item;
+ } else {
+ $values = $depth === 1
+ ? array_values($item)
+ : static::flatten($item, $depth - 1);
+
+ foreach ($values as $value) {
+ $result[] = $value;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Remove one or many array items from a given array using "dot" notation.
+ *
+ * @param array $array
+ * @param array|string $keys
+ * @return void
+ */
+ public static function forget(&$array, $keys)
+ {
+ $original = &$array;
+
+ $keys = (array) $keys;
+
+ if (count($keys) === 0) {
+ return;
+ }
+
+ foreach ($keys as $key) {
+ // if the exact key exists in the top-level, remove it
+ if (static::exists($array, $key)) {
+ unset($array[$key]);
+
+ continue;
+ }
+
+ $parts = explode('.', $key);
+
+ // clean up before each pass
+ $array = &$original;
+
+ while (count($parts) > 1) {
+ $part = array_shift($parts);
+
+ if (isset($array[$part]) && is_array($array[$part])) {
+ $array = &$array[$part];
+ } else {
+ continue 2;
+ }
+ }
+
+ unset($array[array_shift($parts)]);
+ }
+ }
+
+ /**
+ * Get an item from an array using "dot" notation.
+ *
+ * @param \ArrayAccess|array $array
+ * @param string|int|null $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public static function get($array, $key, $default = null)
+ {
+ if (! static::accessible($array)) {
+ return value($default);
+ }
+
+ if (is_null($key)) {
+ return $array;
+ }
+
+ if (static::exists($array, $key)) {
+ return $array[$key];
+ }
+
+ if (strpos($key, '.') === false) {
+ return $array[$key] ?? value($default);
+ }
+
+ foreach (explode('.', $key) as $segment) {
+ if (static::accessible($array) && static::exists($array, $segment)) {
+ $array = $array[$segment];
+ } else {
+ return value($default);
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * Check if an item or items exist in an array using "dot" notation.
+ *
+ * @param \ArrayAccess|array $array
+ * @param string|array $keys
+ * @return bool
+ */
+ public static function has($array, $keys)
+ {
+ $keys = (array) $keys;
+
+ if (! $array || $keys === []) {
+ return false;
+ }
+
+ foreach ($keys as $key) {
+ $subKeyArray = $array;
+
+ if (static::exists($array, $key)) {
+ continue;
+ }
+
+ foreach (explode('.', $key) as $segment) {
+ if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
+ $subKeyArray = $subKeyArray[$segment];
+ } else {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Determine if any of the keys exist in an array using "dot" notation.
+ *
+ * @param \ArrayAccess|array $array
+ * @param string|array $keys
+ * @return bool
+ */
+ public static function hasAny($array, $keys)
+ {
+ if (is_null($keys)) {
+ return false;
+ }
+
+ $keys = (array) $keys;
+
+ if (! $array) {
+ return false;
+ }
+
+ if ($keys === []) {
+ return false;
+ }
+
+ foreach ($keys as $key) {
+ if (static::has($array, $key)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines if an array is associative.
+ *
+ * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
+ *
+ * @param array $array
+ * @return bool
+ */
+ public static function isAssoc(array $array)
+ {
+ $keys = array_keys($array);
+
+ return array_keys($keys) !== $keys;
+ }
+
+ /**
+ * Get a subset of the items from the given array.
+ *
+ * @param array $array
+ * @param array|string $keys
+ * @return array
+ */
+ public static function only($array, $keys)
+ {
+ return array_intersect_key($array, array_flip((array) $keys));
+ }
+
+ /**
+ * Pluck an array of values from an array.
+ *
+ * @param iterable $array
+ * @param string|array|int|null $value
+ * @param string|array|null $key
+ * @return array
+ */
+ public static function pluck($array, $value, $key = null)
+ {
+ $results = [];
+
+ [$value, $key] = static::explodePluckParameters($value, $key);
+
+ foreach ($array as $item) {
+ $itemValue = data_get($item, $value);
+
+ // If the key is "null", we will just append the value to the array and keep
+ // looping. Otherwise we will key the array using the value of the key we
+ // received from the developer. Then we'll return the final array form.
+ if (is_null($key)) {
+ $results[] = $itemValue;
+ } else {
+ $itemKey = data_get($item, $key);
+
+ if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
+ $itemKey = (string) $itemKey;
+ }
+
+ $results[$itemKey] = $itemValue;
+ }
+ }
+
+ return $results;
+ }
+
+ /**
+ * Explode the "value" and "key" arguments passed to "pluck".
+ *
+ * @param string|array $value
+ * @param string|array|null $key
+ * @return array
+ */
+ protected static function explodePluckParameters($value, $key)
+ {
+ $value = is_string($value) ? explode('.', $value) : $value;
+
+ $key = is_null($key) || is_array($key) ? $key : explode('.', $key);
+
+ return [$value, $key];
+ }
+
+ /**
+ * Push an item onto the beginning of an array.
+ *
+ * @param array $array
+ * @param mixed $value
+ * @param mixed $key
+ * @return array
+ */
+ public static function prepend($array, $value, $key = null)
+ {
+ if (func_num_args() == 2) {
+ array_unshift($array, $value);
+ } else {
+ $array = [$key => $value] + $array;
+ }
+
+ return $array;
+ }
+
+ /**
+ * Get a value from the array, and remove it.
+ *
+ * @param array $array
+ * @param string $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public static function pull(&$array, $key, $default = null)
+ {
+ $value = static::get($array, $key, $default);
+
+ static::forget($array, $key);
+
+ return $value;
+ }
+
+ /**
+ * Get one or a specified number of random values from an array.
+ *
+ * @param array $array
+ * @param int|null $number
+ * @param bool|false $preserveKeys
+ * @return mixed
+ *
+ * @throws \InvalidArgumentException
+ */
+ public static function random($array, $number = null, $preserveKeys = false)
+ {
+ $requested = is_null($number) ? 1 : $number;
+
+ $count = count($array);
+
+ if ($requested > $count) {
+ throw new InvalidArgumentException(
+ "You requested {$requested} items, but there are only {$count} items available."
+ );
+ }
+
+ if (is_null($number)) {
+ return $array[array_rand($array)];
+ }
+
+ if ((int) $number === 0) {
+ return [];
+ }
+
+ $keys = array_rand($array, $number);
+
+ $results = [];
+
+ if ($preserveKeys) {
+ foreach ((array) $keys as $key) {
+ $results[$key] = $array[$key];
+ }
+ } else {
+ foreach ((array) $keys as $key) {
+ $results[] = $array[$key];
+ }
+ }
+
+ return $results;
+ }
+
+ /**
+ * Set an array item to a given value using "dot" notation.
+ *
+ * If no key is given to the method, the entire array will be replaced.
+ *
+ * @param array $array
+ * @param string|null $key
+ * @param mixed $value
+ * @return array
+ */
+ public static function set(&$array, $key, $value)
+ {
+ if (is_null($key)) {
+ return $array = $value;
+ }
+
+ $keys = explode('.', $key);
+
+ foreach ($keys as $i => $key) {
+ if (count($keys) === 1) {
+ break;
+ }
+
+ unset($keys[$i]);
+
+ // If the key doesn't exist at this depth, we will just create an empty array
+ // to hold the next value, allowing us to create the arrays to hold final
+ // values at the correct depth. Then we'll keep digging into the array.
+ if (! isset($array[$key]) || ! is_array($array[$key])) {
+ $array[$key] = [];
+ }
+
+ $array = &$array[$key];
+ }
+
+ $array[array_shift($keys)] = $value;
+
+ return $array;
+ }
+
+ /**
+ * Shuffle the given array and return the result.
+ *
+ * @param array $array
+ * @param int|null $seed
+ * @return array
+ */
+ public static function shuffle($array, $seed = null)
+ {
+ if (is_null($seed)) {
+ shuffle($array);
+ } else {
+ mt_srand($seed);
+ shuffle($array);
+ mt_srand();
+ }
+
+ return $array;
+ }
+
+ /**
+ * Sort the array using the given callback or "dot" notation.
+ *
+ * @param array $array
+ * @param callable|array|string|null $callback
+ * @return array
+ */
+ public static function sort($array, $callback = null)
+ {
+ return Collection::make($array)->sortBy($callback)->all();
+ }
+
+ /**
+ * Recursively sort an array by keys and values.
+ *
+ * @param array $array
+ * @param int $options
+ * @param bool $descending
+ * @return array
+ */
+ public static function sortRecursive($array, $options = SORT_REGULAR, $descending = false)
+ {
+ foreach ($array as &$value) {
+ if (is_array($value)) {
+ $value = static::sortRecursive($value, $options, $descending);
+ }
+ }
+
+ if (static::isAssoc($array)) {
+ $descending
+ ? krsort($array, $options)
+ : ksort($array, $options);
+ } else {
+ $descending
+ ? rsort($array, $options)
+ : sort($array, $options);
+ }
+
+ return $array;
+ }
+
+ /**
+ * Convert the array into a query string.
+ *
+ * @param array $array
+ * @return string
+ */
+ public static function query($array)
+ {
+ return http_build_query($array, '', '&', PHP_QUERY_RFC3986);
+ }
+
+ /**
+ * Filter the array using the given callback.
+ *
+ * @param array $array
+ * @param callable $callback
+ * @return array
+ */
+ public static function where($array, callable $callback)
+ {
+ return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
+ }
+
+ /**
+ * If the given value is not an array and not null, wrap it in one.
+ *
+ * @param mixed $value
+ * @return array
+ */
+ public static function wrap($value)
+ {
+ if (is_null($value)) {
+ return [];
+ }
+
+ return is_array($value) ? $value : [$value];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Collection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Collection.php
new file mode 100644
index 0000000..3a0bfbf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Collection.php
@@ -0,0 +1,1453 @@
+<?php
+
+namespace Tightenco\Collect\Support;
+
+use ArrayAccess;
+use ArrayIterator;
+use Tightenco\Collect\Support\Traits\EnumeratesValues;
+use Tightenco\Collect\Support\Traits\Macroable;
+use stdClass;
+
+class Collection implements ArrayAccess, Enumerable
+{
+ use EnumeratesValues, Macroable;
+
+ /**
+ * The items contained in the collection.
+ *
+ * @var array
+ */
+ protected $items = [];
+
+ /**
+ * Create a new collection.
+ *
+ * @param mixed $items
+ * @return void
+ */
+ public function __construct($items = [])
+ {
+ $this->items = $this->getArrayableItems($items);
+ }
+
+ /**
+ * Create a collection with the given range.
+ *
+ * @param int $from
+ * @param int $to
+ * @return static
+ */
+ public static function range($from, $to)
+ {
+ return new static(range($from, $to));
+ }
+
+ /**
+ * Get all of the items in the collection.
+ *
+ * @return array
+ */
+ public function all()
+ {
+ return $this->items;
+ }
+
+ /**
+ * Get a lazy collection for the items in this collection.
+ *
+ * @return \Tightenco\Collect\Support\LazyCollection
+ */
+ public function lazy()
+ {
+ return new LazyCollection($this->items);
+ }
+
+ /**
+ * Get the average value of a given key.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function avg($callback = null)
+ {
+ $callback = $this->valueRetriever($callback);
+
+ $items = $this->map(function ($value) use ($callback) {
+ return $callback($value);
+ })->filter(function ($value) {
+ return ! is_null($value);
+ });
+
+ if ($count = $items->count()) {
+ return $items->sum() / $count;
+ }
+ }
+
+ /**
+ * Get the median of a given key.
+ *
+ * @param string|array|null $key
+ * @return mixed
+ */
+ public function median($key = null)
+ {
+ $values = (isset($key) ? $this->pluck($key) : $this)
+ ->filter(function ($item) {
+ return ! is_null($item);
+ })->sort()->values();
+
+ $count = $values->count();
+
+ if ($count === 0) {
+ return;
+ }
+
+ $middle = (int) ($count / 2);
+
+ if ($count % 2) {
+ return $values->get($middle);
+ }
+
+ return (new static([
+ $values->get($middle - 1), $values->get($middle),
+ ]))->average();
+ }
+
+ /**
+ * Get the mode of a given key.
+ *
+ * @param string|array|null $key
+ * @return array|null
+ */
+ public function mode($key = null)
+ {
+ if ($this->count() === 0) {
+ return;
+ }
+
+ $collection = isset($key) ? $this->pluck($key) : $this;
+
+ $counts = new static;
+
+ $collection->each(function ($value) use ($counts) {
+ $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
+ });
+
+ $sorted = $counts->sort();
+
+ $highestValue = $sorted->last();
+
+ return $sorted->filter(function ($value) use ($highestValue) {
+ return $value == $highestValue;
+ })->sort()->keys()->all();
+ }
+
+ /**
+ * Collapse the collection of items into a single array.
+ *
+ * @return static
+ */
+ public function collapse()
+ {
+ return new static(Arr::collapse($this->items));
+ }
+
+ /**
+ * Determine if an item exists in the collection.
+ *
+ * @param mixed $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return bool
+ */
+ public function contains($key, $operator = null, $value = null)
+ {
+ if (func_num_args() === 1) {
+ if ($this->useAsCallable($key)) {
+ $placeholder = new stdClass;
+
+ return $this->first($key, $placeholder) !== $placeholder;
+ }
+
+ return in_array($key, $this->items);
+ }
+
+ return $this->contains($this->operatorForWhere(...func_get_args()));
+ }
+
+ /**
+ * Cross join with the given lists, returning all possible permutations.
+ *
+ * @param mixed ...$lists
+ * @return static
+ */
+ public function crossJoin(...$lists)
+ {
+ return new static(Arr::crossJoin(
+ $this->items, ...array_map([$this, 'getArrayableItems'], $lists)
+ ));
+ }
+
+ /**
+ * Get the items in the collection that are not present in the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function diff($items)
+ {
+ return new static(array_diff($this->items, $this->getArrayableItems($items)));
+ }
+
+ /**
+ * Get the items in the collection that are not present in the given items, using the callback.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffUsing($items, callable $callback)
+ {
+ return new static(array_udiff($this->items, $this->getArrayableItems($items), $callback));
+ }
+
+ /**
+ * Get the items in the collection whose keys and values are not present in the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function diffAssoc($items)
+ {
+ return new static(array_diff_assoc($this->items, $this->getArrayableItems($items)));
+ }
+
+ /**
+ * Get the items in the collection whose keys and values are not present in the given items, using the callback.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffAssocUsing($items, callable $callback)
+ {
+ return new static(array_diff_uassoc($this->items, $this->getArrayableItems($items), $callback));
+ }
+
+ /**
+ * Get the items in the collection whose keys are not present in the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function diffKeys($items)
+ {
+ return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
+ }
+
+ /**
+ * Get the items in the collection whose keys are not present in the given items, using the callback.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffKeysUsing($items, callable $callback)
+ {
+ return new static(array_diff_ukey($this->items, $this->getArrayableItems($items), $callback));
+ }
+
+ /**
+ * Retrieve duplicate items from the collection.
+ *
+ * @param callable|null $callback
+ * @param bool $strict
+ * @return static
+ */
+ public function duplicates($callback = null, $strict = false)
+ {
+ $items = $this->map($this->valueRetriever($callback));
+
+ $uniqueItems = $items->unique(null, $strict);
+
+ $compare = $this->duplicateComparator($strict);
+
+ $duplicates = new static;
+
+ foreach ($items as $key => $value) {
+ if ($uniqueItems->isNotEmpty() && $compare($value, $uniqueItems->first())) {
+ $uniqueItems->shift();
+ } else {
+ $duplicates[$key] = $value;
+ }
+ }
+
+ return $duplicates;
+ }
+
+ /**
+ * Retrieve duplicate items from the collection using strict comparison.
+ *
+ * @param callable|null $callback
+ * @return static
+ */
+ public function duplicatesStrict($callback = null)
+ {
+ return $this->duplicates($callback, true);
+ }
+
+ /**
+ * Get the comparison function to detect duplicates.
+ *
+ * @param bool $strict
+ * @return \Closure
+ */
+ protected function duplicateComparator($strict)
+ {
+ if ($strict) {
+ return function ($a, $b) {
+ return $a === $b;
+ };
+ }
+
+ return function ($a, $b) {
+ return $a == $b;
+ };
+ }
+
+ /**
+ * Get all items except for those with the specified keys.
+ *
+ * @param \Tightenco\Collect\Support\Collection|mixed $keys
+ * @return static
+ */
+ public function except($keys)
+ {
+ if ($keys instanceof Enumerable) {
+ $keys = $keys->all();
+ } elseif (! is_array($keys)) {
+ $keys = func_get_args();
+ }
+
+ return new static(Arr::except($this->items, $keys));
+ }
+
+ /**
+ * Run a filter over each of the items.
+ *
+ * @param callable|null $callback
+ * @return static
+ */
+ public function filter(callable $callback = null)
+ {
+ if ($callback) {
+ return new static(Arr::where($this->items, $callback));
+ }
+
+ return new static(array_filter($this->items));
+ }
+
+ /**
+ * Get the first item from the collection passing the given truth test.
+ *
+ * @param callable|null $callback
+ * @param mixed $default
+ * @return mixed
+ */
+ public function first(callable $callback = null, $default = null)
+ {
+ return Arr::first($this->items, $callback, $default);
+ }
+
+ /**
+ * Get a flattened array of the items in the collection.
+ *
+ * @param int $depth
+ * @return static
+ */
+ public function flatten($depth = INF)
+ {
+ return new static(Arr::flatten($this->items, $depth));
+ }
+
+ /**
+ * Flip the items in the collection.
+ *
+ * @return static
+ */
+ public function flip()
+ {
+ return new static(array_flip($this->items));
+ }
+
+ /**
+ * Remove an item from the collection by key.
+ *
+ * @param string|array $keys
+ * @return $this
+ */
+ public function forget($keys)
+ {
+ foreach ((array) $keys as $key) {
+ $this->offsetUnset($key);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get an item from the collection by key.
+ *
+ * @param mixed $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public function get($key, $default = null)
+ {
+ if (array_key_exists($key, $this->items)) {
+ return $this->items[$key];
+ }
+
+ return value($default);
+ }
+
+ /**
+ * Group an associative array by a field or using a callback.
+ *
+ * @param array|callable|string $groupBy
+ * @param bool $preserveKeys
+ * @return static
+ */
+ public function groupBy($groupBy, $preserveKeys = false)
+ {
+ if (! $this->useAsCallable($groupBy) && is_array($groupBy)) {
+ $nextGroups = $groupBy;
+
+ $groupBy = array_shift($nextGroups);
+ }
+
+ $groupBy = $this->valueRetriever($groupBy);
+
+ $results = [];
+
+ foreach ($this->items as $key => $value) {
+ $groupKeys = $groupBy($value, $key);
+
+ if (! is_array($groupKeys)) {
+ $groupKeys = [$groupKeys];
+ }
+
+ foreach ($groupKeys as $groupKey) {
+ $groupKey = is_bool($groupKey) ? (int) $groupKey : $groupKey;
+
+ if (! array_key_exists($groupKey, $results)) {
+ $results[$groupKey] = new static;
+ }
+
+ $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
+ }
+ }
+
+ $result = new static($results);
+
+ if (! empty($nextGroups)) {
+ return $result->map->groupBy($nextGroups, $preserveKeys);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Key an associative array by a field or using a callback.
+ *
+ * @param callable|string $keyBy
+ * @return static
+ */
+ public function keyBy($keyBy)
+ {
+ $keyBy = $this->valueRetriever($keyBy);
+
+ $results = [];
+
+ foreach ($this->items as $key => $item) {
+ $resolvedKey = $keyBy($item, $key);
+
+ if (is_object($resolvedKey)) {
+ $resolvedKey = (string) $resolvedKey;
+ }
+
+ $results[$resolvedKey] = $item;
+ }
+
+ return new static($results);
+ }
+
+ /**
+ * Determine if an item exists in the collection by key.
+ *
+ * @param mixed $key
+ * @return bool
+ */
+ public function has($key)
+ {
+ $keys = is_array($key) ? $key : func_get_args();
+
+ foreach ($keys as $value) {
+ if (! array_key_exists($value, $this->items)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Concatenate values of a given key as a string.
+ *
+ * @param string $value
+ * @param string|null $glue
+ * @return string
+ */
+ public function implode($value, $glue = null)
+ {
+ $first = $this->first();
+
+ if (is_array($first) || (is_object($first) && ! $first instanceof \Illuminate\Support\Stringable)) {
+ return implode($glue, $this->pluck($value)->all());
+ }
+
+ return implode($value, $this->items);
+ }
+
+ /**
+ * Intersect the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function intersect($items)
+ {
+ return new static(array_intersect($this->items, $this->getArrayableItems($items)));
+ }
+
+ /**
+ * Intersect the collection with the given items by key.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function intersectByKeys($items)
+ {
+ return new static(array_intersect_key(
+ $this->items, $this->getArrayableItems($items)
+ ));
+ }
+
+ /**
+ * Determine if the collection is empty or not.
+ *
+ * @return bool
+ */
+ public function isEmpty()
+ {
+ return empty($this->items);
+ }
+
+ /**
+ * Determine if the collection contains a single item.
+ *
+ * @return bool
+ */
+ public function containsOneItem()
+ {
+ return $this->count() === 1;
+ }
+
+ /**
+ * Join all items from the collection using a string. The final items can use a separate glue string.
+ *
+ * @param string $glue
+ * @param string $finalGlue
+ * @return string
+ */
+ public function join($glue, $finalGlue = '')
+ {
+ if ($finalGlue === '') {
+ return $this->implode($glue);
+ }
+
+ $count = $this->count();
+
+ if ($count === 0) {
+ return '';
+ }
+
+ if ($count === 1) {
+ return $this->last();
+ }
+
+ $collection = new static($this->items);
+
+ $finalItem = $collection->pop();
+
+ return $collection->implode($glue).$finalGlue.$finalItem;
+ }
+
+ /**
+ * Get the keys of the collection items.
+ *
+ * @return static
+ */
+ public function keys()
+ {
+ return new static(array_keys($this->items));
+ }
+
+ /**
+ * Get the last item from the collection.
+ *
+ * @param callable|null $callback
+ * @param mixed $default
+ * @return mixed
+ */
+ public function last(callable $callback = null, $default = null)
+ {
+ return Arr::last($this->items, $callback, $default);
+ }
+
+ /**
+ * Get the values of a given key.
+ *
+ * @param string|array|int|null $value
+ * @param string|null $key
+ * @return static
+ */
+ public function pluck($value, $key = null)
+ {
+ return new static(Arr::pluck($this->items, $value, $key));
+ }
+
+ /**
+ * Run a map over each of the items.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function map(callable $callback)
+ {
+ $keys = array_keys($this->items);
+
+ $items = array_map($callback, $this->items, $keys);
+
+ return new static(array_combine($keys, $items));
+ }
+
+ /**
+ * Run a dictionary map over the items.
+ *
+ * The callback should return an associative array with a single key/value pair.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapToDictionary(callable $callback)
+ {
+ $dictionary = [];
+
+ foreach ($this->items as $key => $item) {
+ $pair = $callback($item, $key);
+
+ $key = key($pair);
+
+ $value = reset($pair);
+
+ if (! isset($dictionary[$key])) {
+ $dictionary[$key] = [];
+ }
+
+ $dictionary[$key][] = $value;
+ }
+
+ return new static($dictionary);
+ }
+
+ /**
+ * Run an associative map over each of the items.
+ *
+ * The callback should return an associative array with a single key/value pair.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapWithKeys(callable $callback)
+ {
+ $result = [];
+
+ foreach ($this->items as $key => $value) {
+ $assoc = $callback($value, $key);
+
+ foreach ($assoc as $mapKey => $mapValue) {
+ $result[$mapKey] = $mapValue;
+ }
+ }
+
+ return new static($result);
+ }
+
+ /**
+ * Merge the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function merge($items)
+ {
+ return new static(array_merge($this->items, $this->getArrayableItems($items)));
+ }
+
+ /**
+ * Recursively merge the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function mergeRecursive($items)
+ {
+ return new static(array_merge_recursive($this->items, $this->getArrayableItems($items)));
+ }
+
+ /**
+ * Create a collection by using this collection for keys and another for its values.
+ *
+ * @param mixed $values
+ * @return static
+ */
+ public function combine($values)
+ {
+ return new static(array_combine($this->all(), $this->getArrayableItems($values)));
+ }
+
+ /**
+ * Union the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function union($items)
+ {
+ return new static($this->items + $this->getArrayableItems($items));
+ }
+
+ /**
+ * Create a new collection consisting of every n-th element.
+ *
+ * @param int $step
+ * @param int $offset
+ * @return static
+ */
+ public function nth($step, $offset = 0)
+ {
+ $new = [];
+
+ $position = 0;
+
+ foreach ($this->items as $item) {
+ if ($position % $step === $offset) {
+ $new[] = $item;
+ }
+
+ $position++;
+ }
+
+ return new static($new);
+ }
+
+ /**
+ * Get the items with the specified keys.
+ *
+ * @param mixed $keys
+ * @return static
+ */
+ public function only($keys)
+ {
+ if (is_null($keys)) {
+ return new static($this->items);
+ }
+
+ if ($keys instanceof Enumerable) {
+ $keys = $keys->all();
+ }
+
+ $keys = is_array($keys) ? $keys : func_get_args();
+
+ return new static(Arr::only($this->items, $keys));
+ }
+
+ /**
+ * Get and remove the last item from the collection.
+ *
+ * @return mixed
+ */
+ public function pop()
+ {
+ return array_pop($this->items);
+ }
+
+ /**
+ * Push an item onto the beginning of the collection.
+ *
+ * @param mixed $value
+ * @param mixed $key
+ * @return $this
+ */
+ public function prepend($value, $key = null)
+ {
+ $this->items = Arr::prepend($this->items, ...func_get_args());
+
+ return $this;
+ }
+
+ /**
+ * Push one or more items onto the end of the collection.
+ *
+ * @param mixed $values [optional]
+ * @return $this
+ */
+ public function push(...$values)
+ {
+ foreach ($values as $value) {
+ $this->items[] = $value;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Push all of the given items onto the collection.
+ *
+ * @param iterable $source
+ * @return static
+ */
+ public function concat($source)
+ {
+ $result = new static($this);
+
+ foreach ($source as $item) {
+ $result->push($item);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get and remove an item from the collection.
+ *
+ * @param mixed $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public function pull($key, $default = null)
+ {
+ return Arr::pull($this->items, $key, $default);
+ }
+
+ /**
+ * Put an item in the collection by key.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @return $this
+ */
+ public function put($key, $value)
+ {
+ $this->offsetSet($key, $value);
+
+ return $this;
+ }
+
+ /**
+ * Get one or a specified number of items randomly from the collection.
+ *
+ * @param int|null $number
+ * @return static|mixed
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function random($number = null)
+ {
+ if (is_null($number)) {
+ return Arr::random($this->items);
+ }
+
+ return new static(Arr::random($this->items, $number));
+ }
+
+ /**
+ * Replace the collection items with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function replace($items)
+ {
+ return new static(array_replace($this->items, $this->getArrayableItems($items)));
+ }
+
+ /**
+ * Recursively replace the collection items with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function replaceRecursive($items)
+ {
+ return new static(array_replace_recursive($this->items, $this->getArrayableItems($items)));
+ }
+
+ /**
+ * Reverse items order.
+ *
+ * @return static
+ */
+ public function reverse()
+ {
+ return new static(array_reverse($this->items, true));
+ }
+
+ /**
+ * Search the collection for a given value and return the corresponding key if successful.
+ *
+ * @param mixed $value
+ * @param bool $strict
+ * @return mixed
+ */
+ public function search($value, $strict = false)
+ {
+ if (! $this->useAsCallable($value)) {
+ return array_search($value, $this->items, $strict);
+ }
+
+ foreach ($this->items as $key => $item) {
+ if ($value($item, $key)) {
+ return $key;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get and remove the first item from the collection.
+ *
+ * @return mixed
+ */
+ public function shift()
+ {
+ return array_shift($this->items);
+ }
+
+ /**
+ * Shuffle the items in the collection.
+ *
+ * @param int|null $seed
+ * @return static
+ */
+ public function shuffle($seed = null)
+ {
+ return new static(Arr::shuffle($this->items, $seed));
+ }
+
+ /**
+ * Skip the first {$count} items.
+ *
+ * @param int $count
+ * @return static
+ */
+ public function skip($count)
+ {
+ return $this->slice($count);
+ }
+
+ /**
+ * Skip items in the collection until the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function skipUntil($value)
+ {
+ return new static($this->lazy()->skipUntil($value)->all());
+ }
+
+ /**
+ * Skip items in the collection while the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function skipWhile($value)
+ {
+ return new static($this->lazy()->skipWhile($value)->all());
+ }
+
+ /**
+ * Slice the underlying collection array.
+ *
+ * @param int $offset
+ * @param int|null $length
+ * @return static
+ */
+ public function slice($offset, $length = null)
+ {
+ return new static(array_slice($this->items, $offset, $length, true));
+ }
+
+ /**
+ * Split a collection into a certain number of groups.
+ *
+ * @param int $numberOfGroups
+ * @return static
+ */
+ public function split($numberOfGroups)
+ {
+ if ($this->isEmpty()) {
+ return new static;
+ }
+
+ $groups = new static;
+
+ $groupSize = floor($this->count() / $numberOfGroups);
+
+ $remain = $this->count() % $numberOfGroups;
+
+ $start = 0;
+
+ for ($i = 0; $i < $numberOfGroups; $i++) {
+ $size = $groupSize;
+
+ if ($i < $remain) {
+ $size++;
+ }
+
+ if ($size) {
+ $groups->push(new static(array_slice($this->items, $start, $size)));
+
+ $start += $size;
+ }
+ }
+
+ return $groups;
+ }
+
+ /**
+ * Split a collection into a certain number of groups, and fill the first groups completely.
+ *
+ * @param int $numberOfGroups
+ * @return static
+ */
+ public function splitIn($numberOfGroups)
+ {
+ return $this->chunk(ceil($this->count() / $numberOfGroups));
+ }
+
+ /**
+ * Chunk the collection into chunks of the given size.
+ *
+ * @param int $size
+ * @return static
+ */
+ public function chunk($size)
+ {
+ if ($size <= 0) {
+ return new static;
+ }
+
+ $chunks = [];
+
+ foreach (array_chunk($this->items, $size, true) as $chunk) {
+ $chunks[] = new static($chunk);
+ }
+
+ return new static($chunks);
+ }
+
+ /**
+ * Chunk the collection into chunks with a callback.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function chunkWhile(callable $callback)
+ {
+ return new static(
+ $this->lazy()->chunkWhile($callback)->mapInto(static::class)
+ );
+ }
+
+ /**
+ * Sort through each item with a callback.
+ *
+ * @param callable|int|null $callback
+ * @return static
+ */
+ public function sort($callback = null)
+ {
+ $items = $this->items;
+
+ $callback && is_callable($callback)
+ ? uasort($items, $callback)
+ : asort($items, $callback ?? SORT_REGULAR);
+
+ return new static($items);
+ }
+
+ /**
+ * Sort items in descending order.
+ *
+ * @param int $options
+ * @return static
+ */
+ public function sortDesc($options = SORT_REGULAR)
+ {
+ $items = $this->items;
+
+ arsort($items, $options);
+
+ return new static($items);
+ }
+
+ /**
+ * Sort the collection using the given callback.
+ *
+ * @param callable|array|string $callback
+ * @param int $options
+ * @param bool $descending
+ * @return static
+ */
+ public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
+ {
+ if (is_array($callback) && ! is_callable($callback)) {
+ return $this->sortByMany($callback);
+ }
+
+ $results = [];
+
+ $callback = $this->valueRetriever($callback);
+
+ // First we will loop through the items and get the comparator from a callback
+ // function which we were given. Then, we will sort the returned values and
+ // and grab the corresponding values for the sorted keys from this array.
+ foreach ($this->items as $key => $value) {
+ $results[$key] = $callback($value, $key);
+ }
+
+ $descending ? arsort($results, $options)
+ : asort($results, $options);
+
+ // Once we have sorted all of the keys in the array, we will loop through them
+ // and grab the corresponding model so we can set the underlying items list
+ // to the sorted version. Then we'll just return the collection instance.
+ foreach (array_keys($results) as $key) {
+ $results[$key] = $this->items[$key];
+ }
+
+ return new static($results);
+ }
+
+ /**
+ * Sort the collection using multiple comparisons.
+ *
+ * @param array $comparisons
+ * @return static
+ */
+ protected function sortByMany(array $comparisons = [])
+ {
+ $items = $this->items;
+
+ usort($items, function ($a, $b) use ($comparisons) {
+ foreach ($comparisons as $comparison) {
+ $comparison = Arr::wrap($comparison);
+
+ $prop = $comparison[0];
+
+ $ascending = Arr::get($comparison, 1, true) === true ||
+ Arr::get($comparison, 1, true) === 'asc';
+
+ $result = 0;
+
+ if (is_callable($prop)) {
+ $result = $prop($a, $b);
+ } else {
+ $values = [data_get($a, $prop), data_get($b, $prop)];
+
+ if (! $ascending) {
+ $values = array_reverse($values);
+ }
+
+ $result = $values[0] <=> $values[1];
+ }
+
+ if ($result === 0) {
+ continue;
+ }
+
+ return $result;
+ }
+ });
+
+ return new static($items);
+ }
+
+ /**
+ * Sort the collection in descending order using the given callback.
+ *
+ * @param callable|string $callback
+ * @param int $options
+ * @return static
+ */
+ public function sortByDesc($callback, $options = SORT_REGULAR)
+ {
+ return $this->sortBy($callback, $options, true);
+ }
+
+ /**
+ * Sort the collection keys.
+ *
+ * @param int $options
+ * @param bool $descending
+ * @return static
+ */
+ public function sortKeys($options = SORT_REGULAR, $descending = false)
+ {
+ $items = $this->items;
+
+ $descending ? krsort($items, $options) : ksort($items, $options);
+
+ return new static($items);
+ }
+
+ /**
+ * Sort the collection keys in descending order.
+ *
+ * @param int $options
+ * @return static
+ */
+ public function sortKeysDesc($options = SORT_REGULAR)
+ {
+ return $this->sortKeys($options, true);
+ }
+
+ /**
+ * Splice a portion of the underlying collection array.
+ *
+ * @param int $offset
+ * @param int|null $length
+ * @param mixed $replacement
+ * @return static
+ */
+ public function splice($offset, $length = null, $replacement = [])
+ {
+ if (func_num_args() === 1) {
+ return new static(array_splice($this->items, $offset));
+ }
+
+ return new static(array_splice($this->items, $offset, $length, $replacement));
+ }
+
+ /**
+ * Take the first or last {$limit} items.
+ *
+ * @param int $limit
+ * @return static
+ */
+ public function take($limit)
+ {
+ if ($limit < 0) {
+ return $this->slice($limit, abs($limit));
+ }
+
+ return $this->slice(0, $limit);
+ }
+
+ /**
+ * Take items in the collection until the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function takeUntil($value)
+ {
+ return new static($this->lazy()->takeUntil($value)->all());
+ }
+
+ /**
+ * Take items in the collection while the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function takeWhile($value)
+ {
+ return new static($this->lazy()->takeWhile($value)->all());
+ }
+
+ /**
+ * Transform each item in the collection using a callback.
+ *
+ * @param callable $callback
+ * @return $this
+ */
+ public function transform(callable $callback)
+ {
+ $this->items = $this->map($callback)->all();
+
+ return $this;
+ }
+
+ /**
+ * Reset the keys on the underlying array.
+ *
+ * @return static
+ */
+ public function values()
+ {
+ return new static(array_values($this->items));
+ }
+
+ /**
+ * Zip the collection together with one or more arrays.
+ *
+ * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
+ * => [[1, 4], [2, 5], [3, 6]]
+ *
+ * @param mixed ...$items
+ * @return static
+ */
+ public function zip($items)
+ {
+ $arrayableItems = array_map(function ($items) {
+ return $this->getArrayableItems($items);
+ }, func_get_args());
+
+ $params = array_merge([function () {
+ return new static(func_get_args());
+ }, $this->items], $arrayableItems);
+
+ return new static(array_map(...$params));
+ }
+
+ /**
+ * Pad collection to the specified length with a value.
+ *
+ * @param int $size
+ * @param mixed $value
+ * @return static
+ */
+ public function pad($size, $value)
+ {
+ return new static(array_pad($this->items, $size, $value));
+ }
+
+ /**
+ * Get an iterator for the items.
+ *
+ * @return \ArrayIterator
+ */
+ public function getIterator()
+ {
+ return new ArrayIterator($this->items);
+ }
+
+ /**
+ * Count the number of items in the collection.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->items);
+ }
+
+ /**
+ * Count the number of items in the collection by a field or using a callback.
+ *
+ * @param callable|string $countBy
+ * @return static
+ */
+ public function countBy($countBy = null)
+ {
+ return new static($this->lazy()->countBy($countBy)->all());
+ }
+
+ /**
+ * Add an item to the collection.
+ *
+ * @param mixed $item
+ * @return $this
+ */
+ public function add($item)
+ {
+ $this->items[] = $item;
+
+ return $this;
+ }
+
+ /**
+ * Get a base Support collection instance from this collection.
+ *
+ * @return \Tightenco\Collect\Support\Collection
+ */
+ public function toBase()
+ {
+ return new self($this);
+ }
+
+ /**
+ * Determine if an item exists at an offset.
+ *
+ * @param mixed $key
+ * @return bool
+ */
+ public function offsetExists($key)
+ {
+ return isset($this->items[$key]);
+ }
+
+ /**
+ * Get an item at a given offset.
+ *
+ * @param mixed $key
+ * @return mixed
+ */
+ public function offsetGet($key)
+ {
+ return $this->items[$key];
+ }
+
+ /**
+ * Set the item at a given offset.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @return void
+ */
+ public function offsetSet($key, $value)
+ {
+ if (is_null($key)) {
+ $this->items[] = $value;
+ } else {
+ $this->items[$key] = $value;
+ }
+ }
+
+ /**
+ * Unset the item at a given offset.
+ *
+ * @param string $key
+ * @return void
+ */
+ public function offsetUnset($key)
+ {
+ unset($this->items[$key]);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Enumerable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Enumerable.php
new file mode 100644
index 0000000..f189c45
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Enumerable.php
@@ -0,0 +1,1027 @@
+<?php
+
+namespace Tightenco\Collect\Support;
+
+use Countable;
+use Tightenco\Collect\Contracts\Support\Arrayable;
+use Tightenco\Collect\Contracts\Support\Jsonable;
+use IteratorAggregate;
+use JsonSerializable;
+
+interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
+{
+ /**
+ * Create a new collection instance if the value isn't one already.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public static function make($items = []);
+
+ /**
+ * Create a new instance by invoking the callback a given amount of times.
+ *
+ * @param int $number
+ * @param callable|null $callback
+ * @return static
+ */
+ public static function times($number, callable $callback = null);
+
+ /**
+ * Create a collection with the given range.
+ *
+ * @param int $from
+ * @param int $to
+ * @return static
+ */
+ public static function range($from, $to);
+
+ /**
+ * Wrap the given value in a collection if applicable.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public static function wrap($value);
+
+ /**
+ * Get the underlying items from the given collection if applicable.
+ *
+ * @param array|static $value
+ * @return array
+ */
+ public static function unwrap($value);
+
+ /**
+ * Create a new instance with no items.
+ *
+ * @return static
+ */
+ public static function empty();
+
+ /**
+ * Get all items in the enumerable.
+ *
+ * @return array
+ */
+ public function all();
+
+ /**
+ * Alias for the "avg" method.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function average($callback = null);
+
+ /**
+ * Get the median of a given key.
+ *
+ * @param string|array|null $key
+ * @return mixed
+ */
+ public function median($key = null);
+
+ /**
+ * Get the mode of a given key.
+ *
+ * @param string|array|null $key
+ * @return array|null
+ */
+ public function mode($key = null);
+
+ /**
+ * Collapse the items into a single enumerable.
+ *
+ * @return static
+ */
+ public function collapse();
+
+ /**
+ * Alias for the "contains" method.
+ *
+ * @param mixed $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return bool
+ */
+ public function some($key, $operator = null, $value = null);
+
+ /**
+ * Determine if an item exists, using strict comparison.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @return bool
+ */
+ public function containsStrict($key, $value = null);
+
+ /**
+ * Get the average value of a given key.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function avg($callback = null);
+
+ /**
+ * Determine if an item exists in the enumerable.
+ *
+ * @param mixed $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return bool
+ */
+ public function contains($key, $operator = null, $value = null);
+
+ /**
+ * Cross join with the given lists, returning all possible permutations.
+ *
+ * @param mixed ...$lists
+ * @return static
+ */
+ public function crossJoin(...$lists);
+
+ /**
+ * Dump the collection and end the script.
+ *
+ * @param mixed ...$args
+ * @return void
+ */
+ public function dd(...$args);
+
+ /**
+ * Dump the collection.
+ *
+ * @return $this
+ */
+ public function dump();
+
+ /**
+ * Get the items that are not present in the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function diff($items);
+
+ /**
+ * Get the items that are not present in the given items, using the callback.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffUsing($items, callable $callback);
+
+ /**
+ * Get the items whose keys and values are not present in the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function diffAssoc($items);
+
+ /**
+ * Get the items whose keys and values are not present in the given items, using the callback.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffAssocUsing($items, callable $callback);
+
+ /**
+ * Get the items whose keys are not present in the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function diffKeys($items);
+
+ /**
+ * Get the items whose keys are not present in the given items, using the callback.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffKeysUsing($items, callable $callback);
+
+ /**
+ * Retrieve duplicate items.
+ *
+ * @param callable|null $callback
+ * @param bool $strict
+ * @return static
+ */
+ public function duplicates($callback = null, $strict = false);
+
+ /**
+ * Retrieve duplicate items using strict comparison.
+ *
+ * @param callable|null $callback
+ * @return static
+ */
+ public function duplicatesStrict($callback = null);
+
+ /**
+ * Execute a callback over each item.
+ *
+ * @param callable $callback
+ * @return $this
+ */
+ public function each(callable $callback);
+
+ /**
+ * Execute a callback over each nested chunk of items.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function eachSpread(callable $callback);
+
+ /**
+ * Determine if all items pass the given truth test.
+ *
+ * @param string|callable $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return bool
+ */
+ public function every($key, $operator = null, $value = null);
+
+ /**
+ * Get all items except for those with the specified keys.
+ *
+ * @param mixed $keys
+ * @return static
+ */
+ public function except($keys);
+
+ /**
+ * Run a filter over each of the items.
+ *
+ * @param callable|null $callback
+ * @return static
+ */
+ public function filter(callable $callback = null);
+
+ /**
+ * Apply the callback if the value is truthy.
+ *
+ * @param bool $value
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function when($value, callable $callback, callable $default = null);
+
+ /**
+ * Apply the callback if the collection is empty.
+ *
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function whenEmpty(callable $callback, callable $default = null);
+
+ /**
+ * Apply the callback if the collection is not empty.
+ *
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function whenNotEmpty(callable $callback, callable $default = null);
+
+ /**
+ * Apply the callback if the value is falsy.
+ *
+ * @param bool $value
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function unless($value, callable $callback, callable $default = null);
+
+ /**
+ * Apply the callback unless the collection is empty.
+ *
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function unlessEmpty(callable $callback, callable $default = null);
+
+ /**
+ * Apply the callback unless the collection is not empty.
+ *
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function unlessNotEmpty(callable $callback, callable $default = null);
+
+ /**
+ * Filter items by the given key value pair.
+ *
+ * @param string $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return static
+ */
+ public function where($key, $operator = null, $value = null);
+
+ /**
+ * Filter items where the value for the given key is null.
+ *
+ * @param string|null $key
+ * @return static
+ */
+ public function whereNull($key = null);
+
+ /**
+ * Filter items where the value for the given key is not null.
+ *
+ * @param string|null $key
+ * @return static
+ */
+ public function whereNotNull($key = null);
+
+ /**
+ * Filter items by the given key value pair using strict comparison.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return static
+ */
+ public function whereStrict($key, $value);
+
+ /**
+ * Filter items by the given key value pair.
+ *
+ * @param string $key
+ * @param mixed $values
+ * @param bool $strict
+ * @return static
+ */
+ public function whereIn($key, $values, $strict = false);
+
+ /**
+ * Filter items by the given key value pair using strict comparison.
+ *
+ * @param string $key
+ * @param mixed $values
+ * @return static
+ */
+ public function whereInStrict($key, $values);
+
+ /**
+ * Filter items such that the value of the given key is between the given values.
+ *
+ * @param string $key
+ * @param array $values
+ * @return static
+ */
+ public function whereBetween($key, $values);
+
+ /**
+ * Filter items such that the value of the given key is not between the given values.
+ *
+ * @param string $key
+ * @param array $values
+ * @return static
+ */
+ public function whereNotBetween($key, $values);
+
+ /**
+ * Filter items by the given key value pair.
+ *
+ * @param string $key
+ * @param mixed $values
+ * @param bool $strict
+ * @return static
+ */
+ public function whereNotIn($key, $values, $strict = false);
+
+ /**
+ * Filter items by the given key value pair using strict comparison.
+ *
+ * @param string $key
+ * @param mixed $values
+ * @return static
+ */
+ public function whereNotInStrict($key, $values);
+
+ /**
+ * Filter the items, removing any items that don't match the given type(s).
+ *
+ * @param string|string[] $type
+ * @return static
+ */
+ public function whereInstanceOf($type);
+
+ /**
+ * Get the first item from the enumerable passing the given truth test.
+ *
+ * @param callable|null $callback
+ * @param mixed $default
+ * @return mixed
+ */
+ public function first(callable $callback = null, $default = null);
+
+ /**
+ * Get the first item by the given key value pair.
+ *
+ * @param string $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return mixed
+ */
+ public function firstWhere($key, $operator = null, $value = null);
+
+ /**
+ * Get a flattened array of the items in the collection.
+ *
+ * @param int $depth
+ * @return static
+ */
+ public function flatten($depth = INF);
+
+ /**
+ * Flip the values with their keys.
+ *
+ * @return static
+ */
+ public function flip();
+
+ /**
+ * Get an item from the collection by key.
+ *
+ * @param mixed $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public function get($key, $default = null);
+
+ /**
+ * Group an associative array by a field or using a callback.
+ *
+ * @param array|callable|string $groupBy
+ * @param bool $preserveKeys
+ * @return static
+ */
+ public function groupBy($groupBy, $preserveKeys = false);
+
+ /**
+ * Key an associative array by a field or using a callback.
+ *
+ * @param callable|string $keyBy
+ * @return static
+ */
+ public function keyBy($keyBy);
+
+ /**
+ * Determine if an item exists in the collection by key.
+ *
+ * @param mixed $key
+ * @return bool
+ */
+ public function has($key);
+
+ /**
+ * Concatenate values of a given key as a string.
+ *
+ * @param string $value
+ * @param string|null $glue
+ * @return string
+ */
+ public function implode($value, $glue = null);
+
+ /**
+ * Intersect the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function intersect($items);
+
+ /**
+ * Intersect the collection with the given items by key.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function intersectByKeys($items);
+
+ /**
+ * Determine if the collection is empty or not.
+ *
+ * @return bool
+ */
+ public function isEmpty();
+
+ /**
+ * Determine if the collection is not empty.
+ *
+ * @return bool
+ */
+ public function isNotEmpty();
+
+ /**
+ * Join all items from the collection using a string. The final items can use a separate glue string.
+ *
+ * @param string $glue
+ * @param string $finalGlue
+ * @return string
+ */
+ public function join($glue, $finalGlue = '');
+
+ /**
+ * Get the keys of the collection items.
+ *
+ * @return static
+ */
+ public function keys();
+
+ /**
+ * Get the last item from the collection.
+ *
+ * @param callable|null $callback
+ * @param mixed $default
+ * @return mixed
+ */
+ public function last(callable $callback = null, $default = null);
+
+ /**
+ * Run a map over each of the items.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function map(callable $callback);
+
+ /**
+ * Run a map over each nested chunk of items.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapSpread(callable $callback);
+
+ /**
+ * Run a dictionary map over the items.
+ *
+ * The callback should return an associative array with a single key/value pair.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapToDictionary(callable $callback);
+
+ /**
+ * Run a grouping map over the items.
+ *
+ * The callback should return an associative array with a single key/value pair.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapToGroups(callable $callback);
+
+ /**
+ * Run an associative map over each of the items.
+ *
+ * The callback should return an associative array with a single key/value pair.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapWithKeys(callable $callback);
+
+ /**
+ * Map a collection and flatten the result by a single level.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function flatMap(callable $callback);
+
+ /**
+ * Map the values into a new class.
+ *
+ * @param string $class
+ * @return static
+ */
+ public function mapInto($class);
+
+ /**
+ * Merge the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function merge($items);
+
+ /**
+ * Recursively merge the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function mergeRecursive($items);
+
+ /**
+ * Create a collection by using this collection for keys and another for its values.
+ *
+ * @param mixed $values
+ * @return static
+ */
+ public function combine($values);
+
+ /**
+ * Union the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function union($items);
+
+ /**
+ * Get the min value of a given key.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function min($callback = null);
+
+ /**
+ * Get the max value of a given key.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function max($callback = null);
+
+ /**
+ * Create a new collection consisting of every n-th element.
+ *
+ * @param int $step
+ * @param int $offset
+ * @return static
+ */
+ public function nth($step, $offset = 0);
+
+ /**
+ * Get the items with the specified keys.
+ *
+ * @param mixed $keys
+ * @return static
+ */
+ public function only($keys);
+
+ /**
+ * "Paginate" the collection by slicing it into a smaller collection.
+ *
+ * @param int $page
+ * @param int $perPage
+ * @return static
+ */
+ public function forPage($page, $perPage);
+
+ /**
+ * Partition the collection into two arrays using the given callback or key.
+ *
+ * @param callable|string $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return static
+ */
+ public function partition($key, $operator = null, $value = null);
+
+ /**
+ * Push all of the given items onto the collection.
+ *
+ * @param iterable $source
+ * @return static
+ */
+ public function concat($source);
+
+ /**
+ * Get one or a specified number of items randomly from the collection.
+ *
+ * @param int|null $number
+ * @return static|mixed
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function random($number = null);
+
+ /**
+ * Reduce the collection to a single value.
+ *
+ * @param callable $callback
+ * @param mixed $initial
+ * @return mixed
+ */
+ public function reduce(callable $callback, $initial = null);
+
+ /**
+ * Replace the collection items with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function replace($items);
+
+ /**
+ * Recursively replace the collection items with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function replaceRecursive($items);
+
+ /**
+ * Reverse items order.
+ *
+ * @return static
+ */
+ public function reverse();
+
+ /**
+ * Search the collection for a given value and return the corresponding key if successful.
+ *
+ * @param mixed $value
+ * @param bool $strict
+ * @return mixed
+ */
+ public function search($value, $strict = false);
+
+ /**
+ * Shuffle the items in the collection.
+ *
+ * @param int|null $seed
+ * @return static
+ */
+ public function shuffle($seed = null);
+
+ /**
+ * Skip the first {$count} items.
+ *
+ * @param int $count
+ * @return static
+ */
+ public function skip($count);
+
+ /**
+ * Skip items in the collection until the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function skipUntil($value);
+
+ /**
+ * Skip items in the collection while the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function skipWhile($value);
+
+ /**
+ * Get a slice of items from the enumerable.
+ *
+ * @param int $offset
+ * @param int|null $length
+ * @return static
+ */
+ public function slice($offset, $length = null);
+
+ /**
+ * Split a collection into a certain number of groups.
+ *
+ * @param int $numberOfGroups
+ * @return static
+ */
+ public function split($numberOfGroups);
+
+ /**
+ * Chunk the collection into chunks of the given size.
+ *
+ * @param int $size
+ * @return static
+ */
+ public function chunk($size);
+
+ /**
+ * Chunk the collection into chunks with a callback.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function chunkWhile(callable $callback);
+
+ /**
+ * Sort through each item with a callback.
+ *
+ * @param callable|null|int $callback
+ * @return static
+ */
+ public function sort($callback = null);
+
+ /**
+ * Sort items in descending order.
+ *
+ * @param int $options
+ * @return static
+ */
+ public function sortDesc($options = SORT_REGULAR);
+
+ /**
+ * Sort the collection using the given callback.
+ *
+ * @param callable|string $callback
+ * @param int $options
+ * @param bool $descending
+ * @return static
+ */
+ public function sortBy($callback, $options = SORT_REGULAR, $descending = false);
+
+ /**
+ * Sort the collection in descending order using the given callback.
+ *
+ * @param callable|string $callback
+ * @param int $options
+ * @return static
+ */
+ public function sortByDesc($callback, $options = SORT_REGULAR);
+
+ /**
+ * Sort the collection keys.
+ *
+ * @param int $options
+ * @param bool $descending
+ * @return static
+ */
+ public function sortKeys($options = SORT_REGULAR, $descending = false);
+
+ /**
+ * Sort the collection keys in descending order.
+ *
+ * @param int $options
+ * @return static
+ */
+ public function sortKeysDesc($options = SORT_REGULAR);
+
+ /**
+ * Get the sum of the given values.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function sum($callback = null);
+
+ /**
+ * Take the first or last {$limit} items.
+ *
+ * @param int $limit
+ * @return static
+ */
+ public function take($limit);
+
+ /**
+ * Take items in the collection until the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function takeUntil($value);
+
+ /**
+ * Take items in the collection while the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function takeWhile($value);
+
+ /**
+ * Pass the collection to the given callback and then return it.
+ *
+ * @param callable $callback
+ * @return $this
+ */
+ public function tap(callable $callback);
+
+ /**
+ * Pass the enumerable to the given callback and return the result.
+ *
+ * @param callable $callback
+ * @return mixed
+ */
+ public function pipe(callable $callback);
+
+ /**
+ * Get the values of a given key.
+ *
+ * @param string|array $value
+ * @param string|null $key
+ * @return static
+ */
+ public function pluck($value, $key = null);
+
+ /**
+ * Create a collection of all elements that do not pass a given truth test.
+ *
+ * @param callable|mixed $callback
+ * @return static
+ */
+ public function reject($callback = true);
+
+ /**
+ * Return only unique items from the collection array.
+ *
+ * @param string|callable|null $key
+ * @param bool $strict
+ * @return static
+ */
+ public function unique($key = null, $strict = false);
+
+ /**
+ * Return only unique items from the collection array using strict comparison.
+ *
+ * @param string|callable|null $key
+ * @return static
+ */
+ public function uniqueStrict($key = null);
+
+ /**
+ * Reset the keys on the underlying array.
+ *
+ * @return static
+ */
+ public function values();
+
+ /**
+ * Pad collection to the specified length with a value.
+ *
+ * @param int $size
+ * @param mixed $value
+ * @return static
+ */
+ public function pad($size, $value);
+
+ /**
+ * Count the number of items in the collection using a given truth test.
+ *
+ * @param callable|null $callback
+ * @return static
+ */
+ public function countBy($callback = null);
+
+ /**
+ * Zip the collection together with one or more arrays.
+ *
+ * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
+ * => [[1, 4], [2, 5], [3, 6]]
+ *
+ * @param mixed ...$items
+ * @return static
+ */
+ public function zip($items);
+
+ /**
+ * Collect the values into a collection.
+ *
+ * @return \Tightenco\Collect\Support\Collection
+ */
+ public function collect();
+
+ /**
+ * Convert the collection to its string representation.
+ *
+ * @return string
+ */
+ public function __toString();
+
+ /**
+ * Add a method to the list of proxied methods.
+ *
+ * @param string $method
+ * @return void
+ */
+ public static function proxy($method);
+
+ /**
+ * Dynamically access collection proxies.
+ *
+ * @param string $key
+ * @return mixed
+ *
+ * @throws \Exception
+ */
+ public function __get($key);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/HigherOrderCollectionProxy.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/HigherOrderCollectionProxy.php
new file mode 100644
index 0000000..01ac43f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/HigherOrderCollectionProxy.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Tightenco\Collect\Support;
+
+/**
+ * @mixin \Tightenco\Collect\Support\Enumerable
+ */
+class HigherOrderCollectionProxy
+{
+ /**
+ * The collection being operated on.
+ *
+ * @var \Tightenco\Collect\Support\Enumerable
+ */
+ protected $collection;
+
+ /**
+ * The method being proxied.
+ *
+ * @var string
+ */
+ protected $method;
+
+ /**
+ * Create a new proxy instance.
+ *
+ * @param \Tightenco\Collect\Support\Enumerable $collection
+ * @param string $method
+ * @return void
+ */
+ public function __construct(Enumerable $collection, $method)
+ {
+ $this->method = $method;
+ $this->collection = $collection;
+ }
+
+ /**
+ * Proxy accessing an attribute onto the collection items.
+ *
+ * @param string $key
+ * @return mixed
+ */
+ public function __get($key)
+ {
+ return $this->collection->{$this->method}(function ($value) use ($key) {
+ return is_array($value) ? $value[$key] : $value->{$key};
+ });
+ }
+
+ /**
+ * Proxy a method call onto the collection items.
+ *
+ * @param string $method
+ * @param array $parameters
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ return $this->collection->{$this->method}(function ($value) use ($method, $parameters) {
+ return $value->{$method}(...$parameters);
+ });
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/HigherOrderWhenProxy.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/HigherOrderWhenProxy.php
new file mode 100644
index 0000000..ea48c7c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/HigherOrderWhenProxy.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Tightenco\Collect\Support;
+
+/**
+ * @mixin \Tightenco\Collect\Support\Enumerable
+ */
+class HigherOrderWhenProxy
+{
+ /**
+ * The collection being operated on.
+ *
+ * @var \Tightenco\Collect\Support\Enumerable
+ */
+ protected $collection;
+
+ /**
+ * The condition for proxying.
+ *
+ * @var bool
+ */
+ protected $condition;
+
+ /**
+ * Create a new proxy instance.
+ *
+ * @param \Tightenco\Collect\Support\Enumerable $collection
+ * @param bool $condition
+ * @return void
+ */
+ public function __construct(Enumerable $collection, $condition)
+ {
+ $this->condition = $condition;
+ $this->collection = $collection;
+ }
+
+ /**
+ * Proxy accessing an attribute onto the collection.
+ *
+ * @param string $key
+ * @return mixed
+ */
+ public function __get($key)
+ {
+ return $this->condition
+ ? $this->collection->{$key}
+ : $this->collection;
+ }
+
+ /**
+ * Proxy a method call onto the collection.
+ *
+ * @param string $method
+ * @param array $parameters
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ return $this->condition
+ ? $this->collection->{$method}(...$parameters)
+ : $this->collection;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/LazyCollection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/LazyCollection.php
new file mode 100644
index 0000000..da73cb2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/LazyCollection.php
@@ -0,0 +1,1417 @@
+<?php
+
+namespace Tightenco\Collect\Support;
+
+use ArrayIterator;
+use Closure;
+use DateTimeInterface;
+use Tightenco\Collect\Support\Traits\EnumeratesValues;
+use Tightenco\Collect\Support\Traits\Macroable;
+use IteratorAggregate;
+use stdClass;
+
+class LazyCollection implements Enumerable
+{
+ use EnumeratesValues, Macroable;
+
+ /**
+ * The source from which to generate items.
+ *
+ * @var callable|static
+ */
+ public $source;
+
+ /**
+ * Create a new lazy collection instance.
+ *
+ * @param mixed $source
+ * @return void
+ */
+ public function __construct($source = null)
+ {
+ if ($source instanceof Closure || $source instanceof self) {
+ $this->source = $source;
+ } elseif (is_null($source)) {
+ $this->source = static::empty();
+ } else {
+ $this->source = $this->getArrayableItems($source);
+ }
+ }
+
+ /**
+ * Create a collection with the given range.
+ *
+ * @param int $from
+ * @param int $to
+ * @return static
+ */
+ public static function range($from, $to)
+ {
+ return new static(function () use ($from, $to) {
+ if ($from <= $to) {
+ for (; $from <= $to; $from++) {
+ yield $from;
+ }
+ } else {
+ for (; $from >= $to; $from--) {
+ yield $from;
+ }
+ }
+ });
+ }
+
+ /**
+ * Get all items in the enumerable.
+ *
+ * @return array
+ */
+ public function all()
+ {
+ if (is_array($this->source)) {
+ return $this->source;
+ }
+
+ return iterator_to_array($this->getIterator());
+ }
+
+ /**
+ * Eager load all items into a new lazy collection backed by an array.
+ *
+ * @return static
+ */
+ public function eager()
+ {
+ return new static($this->all());
+ }
+
+ /**
+ * Cache values as they're enumerated.
+ *
+ * @return static
+ */
+ public function remember()
+ {
+ $iterator = $this->getIterator();
+
+ $iteratorIndex = 0;
+
+ $cache = [];
+
+ return new static(function () use ($iterator, &$iteratorIndex, &$cache) {
+ for ($index = 0; true; $index++) {
+ if (array_key_exists($index, $cache)) {
+ yield $cache[$index][0] => $cache[$index][1];
+
+ continue;
+ }
+
+ if ($iteratorIndex < $index) {
+ $iterator->next();
+
+ $iteratorIndex++;
+ }
+
+ if (! $iterator->valid()) {
+ break;
+ }
+
+ $cache[$index] = [$iterator->key(), $iterator->current()];
+
+ yield $cache[$index][0] => $cache[$index][1];
+ }
+ });
+ }
+
+ /**
+ * Get the average value of a given key.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function avg($callback = null)
+ {
+ return $this->collect()->avg($callback);
+ }
+
+ /**
+ * Get the median of a given key.
+ *
+ * @param string|array|null $key
+ * @return mixed
+ */
+ public function median($key = null)
+ {
+ return $this->collect()->median($key);
+ }
+
+ /**
+ * Get the mode of a given key.
+ *
+ * @param string|array|null $key
+ * @return array|null
+ */
+ public function mode($key = null)
+ {
+ return $this->collect()->mode($key);
+ }
+
+ /**
+ * Collapse the collection of items into a single array.
+ *
+ * @return static
+ */
+ public function collapse()
+ {
+ return new static(function () {
+ foreach ($this as $values) {
+ if (is_array($values) || $values instanceof Enumerable) {
+ foreach ($values as $value) {
+ yield $value;
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Determine if an item exists in the enumerable.
+ *
+ * @param mixed $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return bool
+ */
+ public function contains($key, $operator = null, $value = null)
+ {
+ if (func_num_args() === 1 && $this->useAsCallable($key)) {
+ $placeholder = new stdClass;
+
+ return $this->first($key, $placeholder) !== $placeholder;
+ }
+
+ if (func_num_args() === 1) {
+ $needle = $key;
+
+ foreach ($this as $value) {
+ if ($value == $needle) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ return $this->contains($this->operatorForWhere(...func_get_args()));
+ }
+
+ /**
+ * Cross join the given iterables, returning all possible permutations.
+ *
+ * @param array ...$arrays
+ * @return static
+ */
+ public function crossJoin(...$arrays)
+ {
+ return $this->passthru('crossJoin', func_get_args());
+ }
+
+ /**
+ * Count the number of items in the collection by a field or using a callback.
+ *
+ * @param callable|string $countBy
+ * @return static
+ */
+ public function countBy($countBy = null)
+ {
+ $countBy = is_null($countBy)
+ ? $this->identity()
+ : $this->valueRetriever($countBy);
+
+ return new static(function () use ($countBy) {
+ $counts = [];
+
+ foreach ($this as $key => $value) {
+ $group = $countBy($value, $key);
+
+ if (empty($counts[$group])) {
+ $counts[$group] = 0;
+ }
+
+ $counts[$group]++;
+ }
+
+ yield from $counts;
+ });
+ }
+
+ /**
+ * Get the items that are not present in the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function diff($items)
+ {
+ return $this->passthru('diff', func_get_args());
+ }
+
+ /**
+ * Get the items that are not present in the given items, using the callback.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffUsing($items, callable $callback)
+ {
+ return $this->passthru('diffUsing', func_get_args());
+ }
+
+ /**
+ * Get the items whose keys and values are not present in the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function diffAssoc($items)
+ {
+ return $this->passthru('diffAssoc', func_get_args());
+ }
+
+ /**
+ * Get the items whose keys and values are not present in the given items, using the callback.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffAssocUsing($items, callable $callback)
+ {
+ return $this->passthru('diffAssocUsing', func_get_args());
+ }
+
+ /**
+ * Get the items whose keys are not present in the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function diffKeys($items)
+ {
+ return $this->passthru('diffKeys', func_get_args());
+ }
+
+ /**
+ * Get the items whose keys are not present in the given items, using the callback.
+ *
+ * @param mixed $items
+ * @param callable $callback
+ * @return static
+ */
+ public function diffKeysUsing($items, callable $callback)
+ {
+ return $this->passthru('diffKeysUsing', func_get_args());
+ }
+
+ /**
+ * Retrieve duplicate items.
+ *
+ * @param callable|null $callback
+ * @param bool $strict
+ * @return static
+ */
+ public function duplicates($callback = null, $strict = false)
+ {
+ return $this->passthru('duplicates', func_get_args());
+ }
+
+ /**
+ * Retrieve duplicate items using strict comparison.
+ *
+ * @param callable|null $callback
+ * @return static
+ */
+ public function duplicatesStrict($callback = null)
+ {
+ return $this->passthru('duplicatesStrict', func_get_args());
+ }
+
+ /**
+ * Get all items except for those with the specified keys.
+ *
+ * @param mixed $keys
+ * @return static
+ */
+ public function except($keys)
+ {
+ return $this->passthru('except', func_get_args());
+ }
+
+ /**
+ * Run a filter over each of the items.
+ *
+ * @param callable|null $callback
+ * @return static
+ */
+ public function filter(callable $callback = null)
+ {
+ if (is_null($callback)) {
+ $callback = function ($value) {
+ return (bool) $value;
+ };
+ }
+
+ return new static(function () use ($callback) {
+ foreach ($this as $key => $value) {
+ if ($callback($value, $key)) {
+ yield $key => $value;
+ }
+ }
+ });
+ }
+
+ /**
+ * Get the first item from the enumerable passing the given truth test.
+ *
+ * @param callable|null $callback
+ * @param mixed $default
+ * @return mixed
+ */
+ public function first(callable $callback = null, $default = null)
+ {
+ $iterator = $this->getIterator();
+
+ if (is_null($callback)) {
+ if (! $iterator->valid()) {
+ return value($default);
+ }
+
+ return $iterator->current();
+ }
+
+ foreach ($iterator as $key => $value) {
+ if ($callback($value, $key)) {
+ return $value;
+ }
+ }
+
+ return value($default);
+ }
+
+ /**
+ * Get a flattened list of the items in the collection.
+ *
+ * @param int $depth
+ * @return static
+ */
+ public function flatten($depth = INF)
+ {
+ $instance = new static(function () use ($depth) {
+ foreach ($this as $item) {
+ if (! is_array($item) && ! $item instanceof Enumerable) {
+ yield $item;
+ } elseif ($depth === 1) {
+ yield from $item;
+ } else {
+ yield from (new static($item))->flatten($depth - 1);
+ }
+ }
+ });
+
+ return $instance->values();
+ }
+
+ /**
+ * Flip the items in the collection.
+ *
+ * @return static
+ */
+ public function flip()
+ {
+ return new static(function () {
+ foreach ($this as $key => $value) {
+ yield $value => $key;
+ }
+ });
+ }
+
+ /**
+ * Get an item by key.
+ *
+ * @param mixed $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public function get($key, $default = null)
+ {
+ if (is_null($key)) {
+ return;
+ }
+
+ foreach ($this as $outerKey => $outerValue) {
+ if ($outerKey == $key) {
+ return $outerValue;
+ }
+ }
+
+ return value($default);
+ }
+
+ /**
+ * Group an associative array by a field or using a callback.
+ *
+ * @param array|callable|string $groupBy
+ * @param bool $preserveKeys
+ * @return static
+ */
+ public function groupBy($groupBy, $preserveKeys = false)
+ {
+ return $this->passthru('groupBy', func_get_args());
+ }
+
+ /**
+ * Key an associative array by a field or using a callback.
+ *
+ * @param callable|string $keyBy
+ * @return static
+ */
+ public function keyBy($keyBy)
+ {
+ return new static(function () use ($keyBy) {
+ $keyBy = $this->valueRetriever($keyBy);
+
+ foreach ($this as $key => $item) {
+ $resolvedKey = $keyBy($item, $key);
+
+ if (is_object($resolvedKey)) {
+ $resolvedKey = (string) $resolvedKey;
+ }
+
+ yield $resolvedKey => $item;
+ }
+ });
+ }
+
+ /**
+ * Determine if an item exists in the collection by key.
+ *
+ * @param mixed $key
+ * @return bool
+ */
+ public function has($key)
+ {
+ $keys = array_flip(is_array($key) ? $key : func_get_args());
+ $count = count($keys);
+
+ foreach ($this as $key => $value) {
+ if (array_key_exists($key, $keys) && --$count == 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Concatenate values of a given key as a string.
+ *
+ * @param string $value
+ * @param string|null $glue
+ * @return string
+ */
+ public function implode($value, $glue = null)
+ {
+ return $this->collect()->implode(...func_get_args());
+ }
+
+ /**
+ * Intersect the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function intersect($items)
+ {
+ return $this->passthru('intersect', func_get_args());
+ }
+
+ /**
+ * Intersect the collection with the given items by key.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function intersectByKeys($items)
+ {
+ return $this->passthru('intersectByKeys', func_get_args());
+ }
+
+ /**
+ * Determine if the items are empty or not.
+ *
+ * @return bool
+ */
+ public function isEmpty()
+ {
+ return ! $this->getIterator()->valid();
+ }
+
+ /**
+ * Determine if the collection contains a single item.
+ *
+ * @return bool
+ */
+ public function containsOneItem()
+ {
+ return $this->take(2)->count() === 1;
+ }
+
+ /**
+ * Join all items from the collection using a string. The final items can use a separate glue string.
+ *
+ * @param string $glue
+ * @param string $finalGlue
+ * @return string
+ */
+ public function join($glue, $finalGlue = '')
+ {
+ return $this->collect()->join(...func_get_args());
+ }
+
+ /**
+ * Get the keys of the collection items.
+ *
+ * @return static
+ */
+ public function keys()
+ {
+ return new static(function () {
+ foreach ($this as $key => $value) {
+ yield $key;
+ }
+ });
+ }
+
+ /**
+ * Get the last item from the collection.
+ *
+ * @param callable|null $callback
+ * @param mixed $default
+ * @return mixed
+ */
+ public function last(callable $callback = null, $default = null)
+ {
+ $needle = $placeholder = new stdClass;
+
+ foreach ($this as $key => $value) {
+ if (is_null($callback) || $callback($value, $key)) {
+ $needle = $value;
+ }
+ }
+
+ return $needle === $placeholder ? value($default) : $needle;
+ }
+
+ /**
+ * Get the values of a given key.
+ *
+ * @param string|array $value
+ * @param string|null $key
+ * @return static
+ */
+ public function pluck($value, $key = null)
+ {
+ return new static(function () use ($value, $key) {
+ [$value, $key] = $this->explodePluckParameters($value, $key);
+
+ foreach ($this as $item) {
+ $itemValue = data_get($item, $value);
+
+ if (is_null($key)) {
+ yield $itemValue;
+ } else {
+ $itemKey = data_get($item, $key);
+
+ if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
+ $itemKey = (string) $itemKey;
+ }
+
+ yield $itemKey => $itemValue;
+ }
+ }
+ });
+ }
+
+ /**
+ * Run a map over each of the items.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function map(callable $callback)
+ {
+ return new static(function () use ($callback) {
+ foreach ($this as $key => $value) {
+ yield $key => $callback($value, $key);
+ }
+ });
+ }
+
+ /**
+ * Run a dictionary map over the items.
+ *
+ * The callback should return an associative array with a single key/value pair.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapToDictionary(callable $callback)
+ {
+ return $this->passthru('mapToDictionary', func_get_args());
+ }
+
+ /**
+ * Run an associative map over each of the items.
+ *
+ * The callback should return an associative array with a single key/value pair.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapWithKeys(callable $callback)
+ {
+ return new static(function () use ($callback) {
+ foreach ($this as $key => $value) {
+ yield from $callback($value, $key);
+ }
+ });
+ }
+
+ /**
+ * Merge the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function merge($items)
+ {
+ return $this->passthru('merge', func_get_args());
+ }
+
+ /**
+ * Recursively merge the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function mergeRecursive($items)
+ {
+ return $this->passthru('mergeRecursive', func_get_args());
+ }
+
+ /**
+ * Create a collection by using this collection for keys and another for its values.
+ *
+ * @param mixed $values
+ * @return static
+ */
+ public function combine($values)
+ {
+ return new static(function () use ($values) {
+ $values = $this->makeIterator($values);
+
+ $errorMessage = 'Both parameters should have an equal number of elements';
+
+ foreach ($this as $key) {
+ if (! $values->valid()) {
+ trigger_error($errorMessage, E_USER_WARNING);
+
+ break;
+ }
+
+ yield $key => $values->current();
+
+ $values->next();
+ }
+
+ if ($values->valid()) {
+ trigger_error($errorMessage, E_USER_WARNING);
+ }
+ });
+ }
+
+ /**
+ * Union the collection with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function union($items)
+ {
+ return $this->passthru('union', func_get_args());
+ }
+
+ /**
+ * Create a new collection consisting of every n-th element.
+ *
+ * @param int $step
+ * @param int $offset
+ * @return static
+ */
+ public function nth($step, $offset = 0)
+ {
+ return new static(function () use ($step, $offset) {
+ $position = 0;
+
+ foreach ($this as $item) {
+ if ($position % $step === $offset) {
+ yield $item;
+ }
+
+ $position++;
+ }
+ });
+ }
+
+ /**
+ * Get the items with the specified keys.
+ *
+ * @param mixed $keys
+ * @return static
+ */
+ public function only($keys)
+ {
+ if ($keys instanceof Enumerable) {
+ $keys = $keys->all();
+ } elseif (! is_null($keys)) {
+ $keys = is_array($keys) ? $keys : func_get_args();
+ }
+
+ return new static(function () use ($keys) {
+ if (is_null($keys)) {
+ yield from $this;
+ } else {
+ $keys = array_flip($keys);
+
+ foreach ($this as $key => $value) {
+ if (array_key_exists($key, $keys)) {
+ yield $key => $value;
+
+ unset($keys[$key]);
+
+ if (empty($keys)) {
+ break;
+ }
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Push all of the given items onto the collection.
+ *
+ * @param iterable $source
+ * @return static
+ */
+ public function concat($source)
+ {
+ return (new static(function () use ($source) {
+ yield from $this;
+ yield from $source;
+ }))->values();
+ }
+
+ /**
+ * Get one or a specified number of items randomly from the collection.
+ *
+ * @param int|null $number
+ * @return static|mixed
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function random($number = null)
+ {
+ $result = $this->collect()->random(...func_get_args());
+
+ return is_null($number) ? $result : new static($result);
+ }
+
+ /**
+ * Replace the collection items with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function replace($items)
+ {
+ return new static(function () use ($items) {
+ $items = $this->getArrayableItems($items);
+
+ foreach ($this as $key => $value) {
+ if (array_key_exists($key, $items)) {
+ yield $key => $items[$key];
+
+ unset($items[$key]);
+ } else {
+ yield $key => $value;
+ }
+ }
+
+ foreach ($items as $key => $value) {
+ yield $key => $value;
+ }
+ });
+ }
+
+ /**
+ * Recursively replace the collection items with the given items.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public function replaceRecursive($items)
+ {
+ return $this->passthru('replaceRecursive', func_get_args());
+ }
+
+ /**
+ * Reverse items order.
+ *
+ * @return static
+ */
+ public function reverse()
+ {
+ return $this->passthru('reverse', func_get_args());
+ }
+
+ /**
+ * Search the collection for a given value and return the corresponding key if successful.
+ *
+ * @param mixed $value
+ * @param bool $strict
+ * @return mixed
+ */
+ public function search($value, $strict = false)
+ {
+ $predicate = $this->useAsCallable($value)
+ ? $value
+ : function ($item) use ($value, $strict) {
+ return $strict ? $item === $value : $item == $value;
+ };
+
+ foreach ($this as $key => $item) {
+ if ($predicate($item, $key)) {
+ return $key;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Shuffle the items in the collection.
+ *
+ * @param int|null $seed
+ * @return static
+ */
+ public function shuffle($seed = null)
+ {
+ return $this->passthru('shuffle', func_get_args());
+ }
+
+ /**
+ * Skip the first {$count} items.
+ *
+ * @param int $count
+ * @return static
+ */
+ public function skip($count)
+ {
+ return new static(function () use ($count) {
+ $iterator = $this->getIterator();
+
+ while ($iterator->valid() && $count--) {
+ $iterator->next();
+ }
+
+ while ($iterator->valid()) {
+ yield $iterator->key() => $iterator->current();
+
+ $iterator->next();
+ }
+ });
+ }
+
+ /**
+ * Skip items in the collection until the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function skipUntil($value)
+ {
+ $callback = $this->useAsCallable($value) ? $value : $this->equality($value);
+
+ return $this->skipWhile($this->negate($callback));
+ }
+
+ /**
+ * Skip items in the collection while the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function skipWhile($value)
+ {
+ $callback = $this->useAsCallable($value) ? $value : $this->equality($value);
+
+ return new static(function () use ($callback) {
+ $iterator = $this->getIterator();
+
+ while ($iterator->valid() && $callback($iterator->current(), $iterator->key())) {
+ $iterator->next();
+ }
+
+ while ($iterator->valid()) {
+ yield $iterator->key() => $iterator->current();
+
+ $iterator->next();
+ }
+ });
+ }
+
+ /**
+ * Get a slice of items from the enumerable.
+ *
+ * @param int $offset
+ * @param int|null $length
+ * @return static
+ */
+ public function slice($offset, $length = null)
+ {
+ if ($offset < 0 || $length < 0) {
+ return $this->passthru('slice', func_get_args());
+ }
+
+ $instance = $this->skip($offset);
+
+ return is_null($length) ? $instance : $instance->take($length);
+ }
+
+ /**
+ * Split a collection into a certain number of groups.
+ *
+ * @param int $numberOfGroups
+ * @return static
+ */
+ public function split($numberOfGroups)
+ {
+ return $this->passthru('split', func_get_args());
+ }
+
+ /**
+ * Chunk the collection into chunks of the given size.
+ *
+ * @param int $size
+ * @return static
+ */
+ public function chunk($size)
+ {
+ if ($size <= 0) {
+ return static::empty();
+ }
+
+ return new static(function () use ($size) {
+ $iterator = $this->getIterator();
+
+ while ($iterator->valid()) {
+ $chunk = [];
+
+ while (true) {
+ $chunk[$iterator->key()] = $iterator->current();
+
+ if (count($chunk) < $size) {
+ $iterator->next();
+
+ if (! $iterator->valid()) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ yield new static($chunk);
+
+ $iterator->next();
+ }
+ });
+ }
+
+ /**
+ * Split a collection into a certain number of groups, and fill the first groups completely.
+ *
+ * @param int $numberOfGroups
+ * @return static
+ */
+ public function splitIn($numberOfGroups)
+ {
+ return $this->chunk(ceil($this->count() / $numberOfGroups));
+ }
+
+ /**
+ * Chunk the collection into chunks with a callback.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function chunkWhile(callable $callback)
+ {
+ return new static(function () use ($callback) {
+ $iterator = $this->getIterator();
+
+ $chunk = new Collection;
+
+ if ($iterator->valid()) {
+ $chunk[$iterator->key()] = $iterator->current();
+
+ $iterator->next();
+ }
+
+ while ($iterator->valid()) {
+ if (! $callback($iterator->current(), $iterator->key(), $chunk)) {
+ yield new static($chunk);
+
+ $chunk = new Collection;
+ }
+
+ $chunk[$iterator->key()] = $iterator->current();
+
+ $iterator->next();
+ }
+
+ if ($chunk->isNotEmpty()) {
+ yield new static($chunk);
+ }
+ });
+ }
+
+ /**
+ * Sort through each item with a callback.
+ *
+ * @param callable|null|int $callback
+ * @return static
+ */
+ public function sort($callback = null)
+ {
+ return $this->passthru('sort', func_get_args());
+ }
+
+ /**
+ * Sort items in descending order.
+ *
+ * @param int $options
+ * @return static
+ */
+ public function sortDesc($options = SORT_REGULAR)
+ {
+ return $this->passthru('sortDesc', func_get_args());
+ }
+
+ /**
+ * Sort the collection using the given callback.
+ *
+ * @param callable|string $callback
+ * @param int $options
+ * @param bool $descending
+ * @return static
+ */
+ public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
+ {
+ return $this->passthru('sortBy', func_get_args());
+ }
+
+ /**
+ * Sort the collection in descending order using the given callback.
+ *
+ * @param callable|string $callback
+ * @param int $options
+ * @return static
+ */
+ public function sortByDesc($callback, $options = SORT_REGULAR)
+ {
+ return $this->passthru('sortByDesc', func_get_args());
+ }
+
+ /**
+ * Sort the collection keys.
+ *
+ * @param int $options
+ * @param bool $descending
+ * @return static
+ */
+ public function sortKeys($options = SORT_REGULAR, $descending = false)
+ {
+ return $this->passthru('sortKeys', func_get_args());
+ }
+
+ /**
+ * Sort the collection keys in descending order.
+ *
+ * @param int $options
+ * @return static
+ */
+ public function sortKeysDesc($options = SORT_REGULAR)
+ {
+ return $this->passthru('sortKeysDesc', func_get_args());
+ }
+
+ /**
+ * Take the first or last {$limit} items.
+ *
+ * @param int $limit
+ * @return static
+ */
+ public function take($limit)
+ {
+ if ($limit < 0) {
+ return $this->passthru('take', func_get_args());
+ }
+
+ return new static(function () use ($limit) {
+ $iterator = $this->getIterator();
+
+ while ($limit--) {
+ if (! $iterator->valid()) {
+ break;
+ }
+
+ yield $iterator->key() => $iterator->current();
+
+ if ($limit) {
+ $iterator->next();
+ }
+ }
+ });
+ }
+
+ /**
+ * Take items in the collection until the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function takeUntil($value)
+ {
+ $callback = $this->useAsCallable($value) ? $value : $this->equality($value);
+
+ return new static(function () use ($callback) {
+ foreach ($this as $key => $item) {
+ if ($callback($item, $key)) {
+ break;
+ }
+
+ yield $key => $item;
+ }
+ });
+ }
+
+ /**
+ * Take items in the collection until a given point in time.
+ *
+ * @param \DateTimeInterface $timeout
+ * @return static
+ */
+ public function takeUntilTimeout(DateTimeInterface $timeout)
+ {
+ $timeout = $timeout->getTimestamp();
+
+ return $this->takeWhile(function () use ($timeout) {
+ return $this->now() < $timeout;
+ });
+ }
+
+ /**
+ * Take items in the collection while the given condition is met.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public function takeWhile($value)
+ {
+ $callback = $this->useAsCallable($value) ? $value : $this->equality($value);
+
+ return $this->takeUntil(function ($item, $key) use ($callback) {
+ return ! $callback($item, $key);
+ });
+ }
+
+ /**
+ * Pass each item in the collection to the given callback, lazily.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function tapEach(callable $callback)
+ {
+ return new static(function () use ($callback) {
+ foreach ($this as $key => $value) {
+ $callback($value, $key);
+
+ yield $key => $value;
+ }
+ });
+ }
+
+ /**
+ * Reset the keys on the underlying array.
+ *
+ * @return static
+ */
+ public function values()
+ {
+ return new static(function () {
+ foreach ($this as $item) {
+ yield $item;
+ }
+ });
+ }
+
+ /**
+ * Zip the collection together with one or more arrays.
+ *
+ * e.g. new LazyCollection([1, 2, 3])->zip([4, 5, 6]);
+ * => [[1, 4], [2, 5], [3, 6]]
+ *
+ * @param mixed ...$items
+ * @return static
+ */
+ public function zip($items)
+ {
+ $iterables = func_get_args();
+
+ return new static(function () use ($iterables) {
+ $iterators = Collection::make($iterables)->map(function ($iterable) {
+ return $this->makeIterator($iterable);
+ })->prepend($this->getIterator());
+
+ while ($iterators->contains->valid()) {
+ yield new static($iterators->map->current());
+
+ $iterators->each->next();
+ }
+ });
+ }
+
+ /**
+ * Pad collection to the specified length with a value.
+ *
+ * @param int $size
+ * @param mixed $value
+ * @return static
+ */
+ public function pad($size, $value)
+ {
+ if ($size < 0) {
+ return $this->passthru('pad', func_get_args());
+ }
+
+ return new static(function () use ($size, $value) {
+ $yielded = 0;
+
+ foreach ($this as $index => $item) {
+ yield $index => $item;
+
+ $yielded++;
+ }
+
+ while ($yielded++ < $size) {
+ yield $value;
+ }
+ });
+ }
+
+ /**
+ * Get the values iterator.
+ *
+ * @return \Traversable
+ */
+ public function getIterator()
+ {
+ return $this->makeIterator($this->source);
+ }
+
+ /**
+ * Count the number of items in the collection.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ if (is_array($this->source)) {
+ return count($this->source);
+ }
+
+ return iterator_count($this->getIterator());
+ }
+
+ /**
+ * Make an iterator from the given source.
+ *
+ * @param mixed $source
+ * @return \Traversable
+ */
+ protected function makeIterator($source)
+ {
+ if ($source instanceof IteratorAggregate) {
+ return $source->getIterator();
+ }
+
+ if (is_array($source)) {
+ return new ArrayIterator($source);
+ }
+
+ return $source();
+ }
+
+ /**
+ * Explode the "value" and "key" arguments passed to "pluck".
+ *
+ * @param string|array $value
+ * @param string|array|null $key
+ * @return array
+ */
+ protected function explodePluckParameters($value, $key)
+ {
+ $value = is_string($value) ? explode('.', $value) : $value;
+
+ $key = is_null($key) || is_array($key) ? $key : explode('.', $key);
+
+ return [$value, $key];
+ }
+
+ /**
+ * Pass this lazy collection through a method on the collection class.
+ *
+ * @param string $method
+ * @param array $params
+ * @return static
+ */
+ protected function passthru($method, array $params)
+ {
+ return new static(function () use ($method, $params) {
+ yield from $this->collect()->$method(...$params);
+ });
+ }
+
+ /**
+ * Get the current time.
+ *
+ * @return int
+ */
+ protected function now()
+ {
+ return time();
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Traits/EnumeratesValues.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Traits/EnumeratesValues.php
new file mode 100644
index 0000000..2ff7d36
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Traits/EnumeratesValues.php
@@ -0,0 +1,1056 @@
+<?php
+
+namespace Tightenco\Collect\Support\Traits;
+
+use CachingIterator;
+use Closure;
+use Exception;
+use Tightenco\Collect\Contracts\Support\Arrayable;
+use Tightenco\Collect\Contracts\Support\Jsonable;
+use Tightenco\Collect\Support\Arr;
+use Tightenco\Collect\Support\Collection;
+use Tightenco\Collect\Support\Enumerable;
+use Tightenco\Collect\Support\HigherOrderCollectionProxy;
+use Tightenco\Collect\Support\HigherOrderWhenProxy;
+use JsonSerializable;
+use Symfony\Component\VarDumper\VarDumper;
+use Traversable;
+
+/**
+ * @property-read HigherOrderCollectionProxy $average
+ * @property-read HigherOrderCollectionProxy $avg
+ * @property-read HigherOrderCollectionProxy $contains
+ * @property-read HigherOrderCollectionProxy $each
+ * @property-read HigherOrderCollectionProxy $every
+ * @property-read HigherOrderCollectionProxy $filter
+ * @property-read HigherOrderCollectionProxy $first
+ * @property-read HigherOrderCollectionProxy $flatMap
+ * @property-read HigherOrderCollectionProxy $groupBy
+ * @property-read HigherOrderCollectionProxy $keyBy
+ * @property-read HigherOrderCollectionProxy $map
+ * @property-read HigherOrderCollectionProxy $max
+ * @property-read HigherOrderCollectionProxy $min
+ * @property-read HigherOrderCollectionProxy $partition
+ * @property-read HigherOrderCollectionProxy $reject
+ * @property-read HigherOrderCollectionProxy $some
+ * @property-read HigherOrderCollectionProxy $sortBy
+ * @property-read HigherOrderCollectionProxy $sortByDesc
+ * @property-read HigherOrderCollectionProxy $skipUntil
+ * @property-read HigherOrderCollectionProxy $skipWhile
+ * @property-read HigherOrderCollectionProxy $sum
+ * @property-read HigherOrderCollectionProxy $takeUntil
+ * @property-read HigherOrderCollectionProxy $takeWhile
+ * @property-read HigherOrderCollectionProxy $unique
+ * @property-read HigherOrderCollectionProxy $until
+ */
+trait EnumeratesValues
+{
+ /**
+ * The methods that can be proxied.
+ *
+ * @var string[]
+ */
+ protected static $proxies = [
+ 'average',
+ 'avg',
+ 'contains',
+ 'each',
+ 'every',
+ 'filter',
+ 'first',
+ 'flatMap',
+ 'groupBy',
+ 'keyBy',
+ 'map',
+ 'max',
+ 'min',
+ 'partition',
+ 'reject',
+ 'skipUntil',
+ 'skipWhile',
+ 'some',
+ 'sortBy',
+ 'sortByDesc',
+ 'sum',
+ 'takeUntil',
+ 'takeWhile',
+ 'unique',
+ 'until',
+ ];
+
+ /**
+ * Create a new collection instance if the value isn't one already.
+ *
+ * @param mixed $items
+ * @return static
+ */
+ public static function make($items = [])
+ {
+ return new static($items);
+ }
+
+ /**
+ * Wrap the given value in a collection if applicable.
+ *
+ * @param mixed $value
+ * @return static
+ */
+ public static function wrap($value)
+ {
+ return $value instanceof Enumerable
+ ? new static($value)
+ : new static(Arr::wrap($value));
+ }
+
+ /**
+ * Get the underlying items from the given collection if applicable.
+ *
+ * @param array|static $value
+ * @return array
+ */
+ public static function unwrap($value)
+ {
+ return $value instanceof Enumerable ? $value->all() : $value;
+ }
+
+ /**
+ * Create a new instance with no items.
+ *
+ * @return static
+ */
+ public static function empty()
+ {
+ return new static([]);
+ }
+
+ /**
+ * Create a new collection by invoking the callback a given amount of times.
+ *
+ * @param int $number
+ * @param callable|null $callback
+ * @return static
+ */
+ public static function times($number, callable $callback = null)
+ {
+ if ($number < 1) {
+ return new static;
+ }
+
+ return static::range(1, $number)
+ ->when($callback)
+ ->map($callback);
+ }
+
+ /**
+ * Alias for the "avg" method.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function average($callback = null)
+ {
+ return $this->avg($callback);
+ }
+
+ /**
+ * Alias for the "contains" method.
+ *
+ * @param mixed $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return bool
+ */
+ public function some($key, $operator = null, $value = null)
+ {
+ return $this->contains(...func_get_args());
+ }
+
+ /**
+ * Determine if an item exists, using strict comparison.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @return bool
+ */
+ public function containsStrict($key, $value = null)
+ {
+ if (func_num_args() === 2) {
+ return $this->contains(function ($item) use ($key, $value) {
+ return data_get($item, $key) === $value;
+ });
+ }
+
+ if ($this->useAsCallable($key)) {
+ return ! is_null($this->first($key));
+ }
+
+ foreach ($this as $item) {
+ if ($item === $key) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Dump the items and end the script.
+ *
+ * @param mixed ...$args
+ * @return void
+ */
+ public function dd(...$args)
+ {
+ $this->dump(...$args);
+
+ exit(1);
+ }
+
+ /**
+ * Dump the items.
+ *
+ * @return $this
+ */
+ public function dump()
+ {
+ (new Collection(func_get_args()))
+ ->push($this->all())
+ ->each(function ($item) {
+ VarDumper::dump($item);
+ });
+
+ return $this;
+ }
+
+ /**
+ * Execute a callback over each item.
+ *
+ * @param callable $callback
+ * @return $this
+ */
+ public function each(callable $callback)
+ {
+ foreach ($this as $key => $item) {
+ if ($callback($item, $key) === false) {
+ break;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Execute a callback over each nested chunk of items.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function eachSpread(callable $callback)
+ {
+ return $this->each(function ($chunk, $key) use ($callback) {
+ $chunk[] = $key;
+
+ return $callback(...$chunk);
+ });
+ }
+
+ /**
+ * Determine if all items pass the given truth test.
+ *
+ * @param string|callable $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return bool
+ */
+ public function every($key, $operator = null, $value = null)
+ {
+ if (func_num_args() === 1) {
+ $callback = $this->valueRetriever($key);
+
+ foreach ($this as $k => $v) {
+ if (! $callback($v, $k)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return $this->every($this->operatorForWhere(...func_get_args()));
+ }
+
+ /**
+ * Get the first item by the given key value pair.
+ *
+ * @param string $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return mixed
+ */
+ public function firstWhere($key, $operator = null, $value = null)
+ {
+ return $this->first($this->operatorForWhere(...func_get_args()));
+ }
+
+ /**
+ * Determine if the collection is not empty.
+ *
+ * @return bool
+ */
+ public function isNotEmpty()
+ {
+ return ! $this->isEmpty();
+ }
+
+ /**
+ * Run a map over each nested chunk of items.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapSpread(callable $callback)
+ {
+ return $this->map(function ($chunk, $key) use ($callback) {
+ $chunk[] = $key;
+
+ return $callback(...$chunk);
+ });
+ }
+
+ /**
+ * Run a grouping map over the items.
+ *
+ * The callback should return an associative array with a single key/value pair.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function mapToGroups(callable $callback)
+ {
+ $groups = $this->mapToDictionary($callback);
+
+ return $groups->map([$this, 'make']);
+ }
+
+ /**
+ * Map a collection and flatten the result by a single level.
+ *
+ * @param callable $callback
+ * @return static
+ */
+ public function flatMap(callable $callback)
+ {
+ return $this->map($callback)->collapse();
+ }
+
+ /**
+ * Map the values into a new class.
+ *
+ * @param string $class
+ * @return static
+ */
+ public function mapInto($class)
+ {
+ return $this->map(function ($value, $key) use ($class) {
+ return new $class($value, $key);
+ });
+ }
+
+ /**
+ * Get the min value of a given key.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function min($callback = null)
+ {
+ $callback = $this->valueRetriever($callback);
+
+ return $this->map(function ($value) use ($callback) {
+ return $callback($value);
+ })->filter(function ($value) {
+ return ! is_null($value);
+ })->reduce(function ($result, $value) {
+ return is_null($result) || $value < $result ? $value : $result;
+ });
+ }
+
+ /**
+ * Get the max value of a given key.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function max($callback = null)
+ {
+ $callback = $this->valueRetriever($callback);
+
+ return $this->filter(function ($value) {
+ return ! is_null($value);
+ })->reduce(function ($result, $item) use ($callback) {
+ $value = $callback($item);
+
+ return is_null($result) || $value > $result ? $value : $result;
+ });
+ }
+
+ /**
+ * "Paginate" the collection by slicing it into a smaller collection.
+ *
+ * @param int $page
+ * @param int $perPage
+ * @return static
+ */
+ public function forPage($page, $perPage)
+ {
+ $offset = max(0, ($page - 1) * $perPage);
+
+ return $this->slice($offset, $perPage);
+ }
+
+ /**
+ * Partition the collection into two arrays using the given callback or key.
+ *
+ * @param callable|string $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return static
+ */
+ public function partition($key, $operator = null, $value = null)
+ {
+ $passed = [];
+ $failed = [];
+
+ $callback = func_num_args() === 1
+ ? $this->valueRetriever($key)
+ : $this->operatorForWhere(...func_get_args());
+
+ foreach ($this as $key => $item) {
+ if ($callback($item, $key)) {
+ $passed[$key] = $item;
+ } else {
+ $failed[$key] = $item;
+ }
+ }
+
+ return new static([new static($passed), new static($failed)]);
+ }
+
+ /**
+ * Get the sum of the given values.
+ *
+ * @param callable|string|null $callback
+ * @return mixed
+ */
+ public function sum($callback = null)
+ {
+ $callback = is_null($callback)
+ ? $this->identity()
+ : $this->valueRetriever($callback);
+
+ return $this->reduce(function ($result, $item) use ($callback) {
+ return $result + $callback($item);
+ }, 0);
+ }
+
+ /**
+ * Apply the callback if the value is truthy.
+ *
+ * @param bool|mixed $value
+ * @param callable|null $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function when($value, callable $callback = null, callable $default = null)
+ {
+ if (! $callback) {
+ return new HigherOrderWhenProxy($this, $value);
+ }
+
+ if ($value) {
+ return $callback($this, $value);
+ } elseif ($default) {
+ return $default($this, $value);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Apply the callback if the collection is empty.
+ *
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function whenEmpty(callable $callback, callable $default = null)
+ {
+ return $this->when($this->isEmpty(), $callback, $default);
+ }
+
+ /**
+ * Apply the callback if the collection is not empty.
+ *
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function whenNotEmpty(callable $callback, callable $default = null)
+ {
+ return $this->when($this->isNotEmpty(), $callback, $default);
+ }
+
+ /**
+ * Apply the callback if the value is falsy.
+ *
+ * @param bool $value
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function unless($value, callable $callback, callable $default = null)
+ {
+ return $this->when(! $value, $callback, $default);
+ }
+
+ /**
+ * Apply the callback unless the collection is empty.
+ *
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function unlessEmpty(callable $callback, callable $default = null)
+ {
+ return $this->whenNotEmpty($callback, $default);
+ }
+
+ /**
+ * Apply the callback unless the collection is not empty.
+ *
+ * @param callable $callback
+ * @param callable|null $default
+ * @return static|mixed
+ */
+ public function unlessNotEmpty(callable $callback, callable $default = null)
+ {
+ return $this->whenEmpty($callback, $default);
+ }
+
+ /**
+ * Filter items by the given key value pair.
+ *
+ * @param string $key
+ * @param mixed $operator
+ * @param mixed $value
+ * @return static
+ */
+ public function where($key, $operator = null, $value = null)
+ {
+ return $this->filter($this->operatorForWhere(...func_get_args()));
+ }
+
+ /**
+ * Filter items where the value for the given key is null.
+ *
+ * @param string|null $key
+ * @return static
+ */
+ public function whereNull($key = null)
+ {
+ return $this->whereStrict($key, null);
+ }
+
+ /**
+ * Filter items where the value for the given key is not null.
+ *
+ * @param string|null $key
+ * @return static
+ */
+ public function whereNotNull($key = null)
+ {
+ return $this->where($key, '!==', null);
+ }
+
+ /**
+ * Filter items by the given key value pair using strict comparison.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return static
+ */
+ public function whereStrict($key, $value)
+ {
+ return $this->where($key, '===', $value);
+ }
+
+ /**
+ * Filter items by the given key value pair.
+ *
+ * @param string $key
+ * @param mixed $values
+ * @param bool $strict
+ * @return static
+ */
+ public function whereIn($key, $values, $strict = false)
+ {
+ $values = $this->getArrayableItems($values);
+
+ return $this->filter(function ($item) use ($key, $values, $strict) {
+ return in_array(data_get($item, $key), $values, $strict);
+ });
+ }
+
+ /**
+ * Filter items by the given key value pair using strict comparison.
+ *
+ * @param string $key
+ * @param mixed $values
+ * @return static
+ */
+ public function whereInStrict($key, $values)
+ {
+ return $this->whereIn($key, $values, true);
+ }
+
+ /**
+ * Filter items such that the value of the given key is between the given values.
+ *
+ * @param string $key
+ * @param array $values
+ * @return static
+ */
+ public function whereBetween($key, $values)
+ {
+ return $this->where($key, '>=', reset($values))->where($key, '<=', end($values));
+ }
+
+ /**
+ * Filter items such that the value of the given key is not between the given values.
+ *
+ * @param string $key
+ * @param array $values
+ * @return static
+ */
+ public function whereNotBetween($key, $values)
+ {
+ return $this->filter(function ($item) use ($key, $values) {
+ return data_get($item, $key) < reset($values) || data_get($item, $key) > end($values);
+ });
+ }
+
+ /**
+ * Filter items by the given key value pair.
+ *
+ * @param string $key
+ * @param mixed $values
+ * @param bool $strict
+ * @return static
+ */
+ public function whereNotIn($key, $values, $strict = false)
+ {
+ $values = $this->getArrayableItems($values);
+
+ return $this->reject(function ($item) use ($key, $values, $strict) {
+ return in_array(data_get($item, $key), $values, $strict);
+ });
+ }
+
+ /**
+ * Filter items by the given key value pair using strict comparison.
+ *
+ * @param string $key
+ * @param mixed $values
+ * @return static
+ */
+ public function whereNotInStrict($key, $values)
+ {
+ return $this->whereNotIn($key, $values, true);
+ }
+
+ /**
+ * Filter the items, removing any items that don't match the given type(s).
+ *
+ * @param string|string[] $type
+ * @return static
+ */
+ public function whereInstanceOf($type)
+ {
+ return $this->filter(function ($value) use ($type) {
+ if (is_array($type)) {
+ foreach ($type as $classType) {
+ if ($value instanceof $classType) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ return $value instanceof $type;
+ });
+ }
+
+ /**
+ * Pass the collection to the given callback and return the result.
+ *
+ * @param callable $callback
+ * @return mixed
+ */
+ public function pipe(callable $callback)
+ {
+ return $callback($this);
+ }
+
+ /**
+ * Pass the collection into a new class.
+ *
+ * @param string $class
+ * @return mixed
+ */
+ public function pipeInto($class)
+ {
+ return new $class($this);
+ }
+
+ /**
+ * Pass the collection to the given callback and then return it.
+ *
+ * @param callable $callback
+ * @return $this
+ */
+ public function tap(callable $callback)
+ {
+ $callback(clone $this);
+
+ return $this;
+ }
+
+ /**
+ * Reduce the collection to a single value.
+ *
+ * @param callable $callback
+ * @param mixed $initial
+ * @return mixed
+ */
+ public function reduce(callable $callback, $initial = null)
+ {
+ $result = $initial;
+
+ foreach ($this as $key => $value) {
+ $result = $callback($result, $value, $key);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Reduce an associative collection to a single value.
+ *
+ * @param callable $callback
+ * @param mixed $initial
+ * @return mixed
+ */
+ public function reduceWithKeys(callable $callback, $initial = null)
+ {
+ $result = $initial;
+
+ foreach ($this as $key => $value) {
+ $result = $callback($result, $value, $key);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Create a collection of all elements that do not pass a given truth test.
+ *
+ * @param callable|mixed $callback
+ * @return static
+ */
+ public function reject($callback = true)
+ {
+ $useAsCallable = $this->useAsCallable($callback);
+
+ return $this->filter(function ($value, $key) use ($callback, $useAsCallable) {
+ return $useAsCallable
+ ? ! $callback($value, $key)
+ : $value != $callback;
+ });
+ }
+
+ /**
+ * Return only unique items from the collection array.
+ *
+ * @param string|callable|null $key
+ * @param bool $strict
+ * @return static
+ */
+ public function unique($key = null, $strict = false)
+ {
+ $callback = $this->valueRetriever($key);
+
+ $exists = [];
+
+ return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
+ if (in_array($id = $callback($item, $key), $exists, $strict)) {
+ return true;
+ }
+
+ $exists[] = $id;
+ });
+ }
+
+ /**
+ * Return only unique items from the collection array using strict comparison.
+ *
+ * @param string|callable|null $key
+ * @return static
+ */
+ public function uniqueStrict($key = null)
+ {
+ return $this->unique($key, true);
+ }
+
+ /**
+ * Collect the values into a collection.
+ *
+ * @return \Tightenco\Collect\Support\Collection
+ */
+ public function collect()
+ {
+ return new Collection($this->all());
+ }
+
+ /**
+ * Get the collection of items as a plain array.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ return $this->map(function ($value) {
+ return $value instanceof Arrayable ? $value->toArray() : $value;
+ })->all();
+ }
+
+ /**
+ * Convert the object into something JSON serializable.
+ *
+ * @return array
+ */
+ public function jsonSerialize()
+ {
+ return array_map(function ($value) {
+ if ($value instanceof JsonSerializable) {
+ return $value->jsonSerialize();
+ } elseif ($value instanceof Jsonable) {
+ return json_decode($value->toJson(), true);
+ } elseif ($value instanceof Arrayable) {
+ return $value->toArray();
+ }
+
+ return $value;
+ }, $this->all());
+ }
+
+ /**
+ * Get the collection of items as JSON.
+ *
+ * @param int $options
+ * @return string
+ */
+ public function toJson($options = 0)
+ {
+ return json_encode($this->jsonSerialize(), $options);
+ }
+
+ /**
+ * Get a CachingIterator instance.
+ *
+ * @param int $flags
+ * @return \CachingIterator
+ */
+ public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
+ {
+ return new CachingIterator($this->getIterator(), $flags);
+ }
+
+ /**
+ * Convert the collection to its string representation.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toJson();
+ }
+
+ /**
+ * Add a method to the list of proxied methods.
+ *
+ * @param string $method
+ * @return void
+ */
+ public static function proxy($method)
+ {
+ static::$proxies[] = $method;
+ }
+
+ /**
+ * Dynamically access collection proxies.
+ *
+ * @param string $key
+ * @return mixed
+ *
+ * @throws \Exception
+ */
+ public function __get($key)
+ {
+ if (! in_array($key, static::$proxies)) {
+ throw new Exception("Property [{$key}] does not exist on this collection instance.");
+ }
+
+ return new HigherOrderCollectionProxy($this, $key);
+ }
+
+ /**
+ * Results array of items from Collection or Arrayable.
+ *
+ * @param mixed $items
+ * @return array
+ */
+ protected function getArrayableItems($items)
+ {
+ if (is_array($items)) {
+ return $items;
+ } elseif ($items instanceof Enumerable) {
+ return $items->all();
+ } elseif ($items instanceof Arrayable) {
+ return $items->toArray();
+ } elseif ($items instanceof Jsonable) {
+ return json_decode($items->toJson(), true);
+ } elseif ($items instanceof JsonSerializable) {
+ return (array) $items->jsonSerialize();
+ } elseif ($items instanceof Traversable) {
+ return iterator_to_array($items);
+ }
+
+ return (array) $items;
+ }
+
+ /**
+ * Get an operator checker callback.
+ *
+ * @param string $key
+ * @param string|null $operator
+ * @param mixed $value
+ * @return \Closure
+ */
+ protected function operatorForWhere($key, $operator = null, $value = null)
+ {
+ if (func_num_args() === 1) {
+ $value = true;
+
+ $operator = '=';
+ }
+
+ if (func_num_args() === 2) {
+ $value = $operator;
+
+ $operator = '=';
+ }
+
+ return function ($item) use ($key, $operator, $value) {
+ $retrieved = data_get($item, $key);
+
+ $strings = array_filter([$retrieved, $value], function ($value) {
+ return is_string($value) || (is_object($value) && method_exists($value, '__toString'));
+ });
+
+ if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
+ return in_array($operator, ['!=', '<>', '!==']);
+ }
+
+ switch ($operator) {
+ default:
+ case '=':
+ case '==': return $retrieved == $value;
+ case '!=':
+ case '<>': return $retrieved != $value;
+ case '<': return $retrieved < $value;
+ case '>': return $retrieved > $value;
+ case '<=': return $retrieved <= $value;
+ case '>=': return $retrieved >= $value;
+ case '===': return $retrieved === $value;
+ case '!==': return $retrieved !== $value;
+ }
+ };
+ }
+
+ /**
+ * Determine if the given value is callable, but not a string.
+ *
+ * @param mixed $value
+ * @return bool
+ */
+ protected function useAsCallable($value)
+ {
+ return ! is_string($value) && is_callable($value);
+ }
+
+ /**
+ * Get a value retrieving callback.
+ *
+ * @param callable|string|null $value
+ * @return callable
+ */
+ protected function valueRetriever($value)
+ {
+ if ($this->useAsCallable($value)) {
+ return $value;
+ }
+
+ return function ($item) use ($value) {
+ return data_get($item, $value);
+ };
+ }
+
+ /**
+ * Make a function to check an item's equality.
+ *
+ * @param mixed $value
+ * @return \Closure
+ */
+ protected function equality($value)
+ {
+ return function ($item) use ($value) {
+ return $item === $value;
+ };
+ }
+
+ /**
+ * Make a function using another function, by negating its result.
+ *
+ * @param \Closure $callback
+ * @return \Closure
+ */
+ protected function negate(Closure $callback)
+ {
+ return function (...$params) use ($callback) {
+ return ! $callback(...$params);
+ };
+ }
+
+ /**
+ * Make a function that returns what's passed to it.
+ *
+ * @return \Closure
+ */
+ protected function identity()
+ {
+ return function ($value) {
+ return $value;
+ };
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Traits/Macroable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Traits/Macroable.php
new file mode 100644
index 0000000..d9b5fe7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Traits/Macroable.php
@@ -0,0 +1,116 @@
+<?php
+
+namespace Tightenco\Collect\Support\Traits;
+
+use BadMethodCallException;
+use Closure;
+use ReflectionClass;
+use ReflectionMethod;
+
+trait Macroable
+{
+ /**
+ * The registered string macros.
+ *
+ * @var array
+ */
+ protected static $macros = [];
+
+ /**
+ * Register a custom macro.
+ *
+ * @param string $name
+ * @param object|callable $macro
+ * @return void
+ */
+ public static function macro($name, $macro)
+ {
+ static::$macros[$name] = $macro;
+ }
+
+ /**
+ * Mix another object into the class.
+ *
+ * @param object $mixin
+ * @param bool $replace
+ * @return void
+ *
+ * @throws \ReflectionException
+ */
+ public static function mixin($mixin, $replace = true)
+ {
+ $methods = (new ReflectionClass($mixin))->getMethods(
+ ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
+ );
+
+ foreach ($methods as $method) {
+ if ($replace || ! static::hasMacro($method->name)) {
+ $method->setAccessible(true);
+ static::macro($method->name, $method->invoke($mixin));
+ }
+ }
+ }
+
+ /**
+ * Checks if macro is registered.
+ *
+ * @param string $name
+ * @return bool
+ */
+ public static function hasMacro($name)
+ {
+ return isset(static::$macros[$name]);
+ }
+
+ /**
+ * Dynamically handle calls to the class.
+ *
+ * @param string $method
+ * @param array $parameters
+ * @return mixed
+ *
+ * @throws \BadMethodCallException
+ */
+ public static function __callStatic($method, $parameters)
+ {
+ if (! static::hasMacro($method)) {
+ throw new BadMethodCallException(sprintf(
+ 'Method %s::%s does not exist.', static::class, $method
+ ));
+ }
+
+ $macro = static::$macros[$method];
+
+ if ($macro instanceof Closure) {
+ $macro = $macro->bindTo(null, static::class);
+ }
+
+ return $macro(...$parameters);
+ }
+
+ /**
+ * Dynamically handle calls to the class.
+ *
+ * @param string $method
+ * @param array $parameters
+ * @return mixed
+ *
+ * @throws \BadMethodCallException
+ */
+ public function __call($method, $parameters)
+ {
+ if (! static::hasMacro($method)) {
+ throw new BadMethodCallException(sprintf(
+ 'Method %s::%s does not exist.', static::class, $method
+ ));
+ }
+
+ $macro = static::$macros[$method];
+
+ if ($macro instanceof Closure) {
+ $macro = $macro->bindTo($this, static::class);
+ }
+
+ return $macro(...$parameters);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Traits/Tappable.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Traits/Tappable.php
new file mode 100644
index 0000000..17e6b9e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/Traits/Tappable.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Tightenco\Collect\Support\Traits;
+
+trait Tappable
+{
+ /**
+ * Call the given Closure with this instance then return the instance.
+ *
+ * @param callable|null $callback
+ * @return mixed
+ */
+ public function tap($callback = null)
+ {
+ return tap($this, $callback);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/alias.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/alias.php
new file mode 100644
index 0000000..1ecffd3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/alias.php
@@ -0,0 +1,20 @@
+<?php
+
+$aliases = [
+ Tightenco\Collect\Contracts\Support\Arrayable::class => Illuminate\Contracts\Support\Arrayable::class,
+ Tightenco\Collect\Contracts\Support\Jsonable::class => Illuminate\Contracts\Support\Jsonable::class,
+ Tightenco\Collect\Contracts\Support\Htmlable::class => Illuminate\Contracts\Support\Htmlable::class,
+ Tightenco\Collect\Support\Arr::class => Illuminate\Support\Arr::class,
+ Tightenco\Collect\Support\Collection::class => Illuminate\Support\Collection::class,
+ Tightenco\Collect\Support\Enumerable::class => Illuminate\Support\Enumerable::class,
+ Tightenco\Collect\Support\HigherOrderCollectionProxy::class => Illuminate\Support\HigherOrderCollectionProxy::class,
+ Tightenco\Collect\Support\HigherOrderWhenProxy::class => Illuminate\Support\HigherOrderWhenProxy::class,
+ Tightenco\Collect\Support\LazyCollection::class => Illuminate\Support\LazyCollection::class,
+ Tightenco\Collect\Support\Traits\EnumeratesValues::class => Illuminate\Support\Traits\EnumeratesValues::class,
+];
+
+foreach ($aliases as $tighten => $illuminate) {
+ if (! class_exists($illuminate) && ! interface_exists($illuminate) && ! trait_exists($illuminate)) {
+ class_alias($tighten, $illuminate);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/helpers.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/helpers.php
new file mode 100644
index 0000000..d7f9e0e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/tightenco/collect/src/Collect/Support/helpers.php
@@ -0,0 +1,139 @@
+<?php
+
+use Tightenco\Collect\Support\Arr;
+use Tightenco\Collect\Support\Collection;
+use Tightenco\Collect\Support\HigherOrderTapProxy;
+use Symfony\Component\VarDumper\VarDumper;
+
+if (! class_exists(Illuminate\Support\Collection::class)) {
+ if (! function_exists('array_wrap')) {
+ /**
+ * If the given value is not an array, wrap it in one.
+ *
+ * @param mixed $value
+ * @return array
+ */
+ function array_wrap($value)
+ {
+ return ! is_array($value) ? [$value] : $value;
+ }
+ }
+
+ if (! function_exists('collect')) {
+ /**
+ * Create a collection from the given value.
+ *
+ * @param mixed $value
+ * @return \Tightenco\Collect\Support\Collection
+ */
+ function collect($value = null)
+ {
+ return new Collection($value);
+ }
+ }
+
+ if (! function_exists('value')) {
+ /**
+ * Return the default value of the given value.
+ *
+ * @param mixed $value
+ * @return mixed
+ */
+ function value($value)
+ {
+ return $value instanceof Closure ? $value() : $value;
+ }
+ }
+
+ if (! function_exists('data_get')) {
+ /**
+ * Get an item from an array or object using "dot" notation.
+ *
+ * @param mixed $target
+ * @param string|array $key
+ * @param mixed $default
+ * @return mixed
+ */
+ function data_get($target, $key, $default = null)
+ {
+ if (is_null($key)) {
+ return $target;
+ }
+
+ $key = is_array($key) ? $key : explode('.', $key);
+
+ while (($segment = array_shift($key)) !== null) {
+ if ($segment === '*') {
+ if ($target instanceof Collection) {
+ $target = $target->all();
+ } elseif (! is_array($target)) {
+ return value($default);
+ }
+
+ $result = Arr::pluck($target, $key);
+
+ return in_array('*', $key) ? Arr::collapse($result) : $result;
+ }
+
+ if (Arr::accessible($target) && Arr::exists($target, $segment)) {
+ $target = $target[$segment];
+ } elseif (is_object($target) && isset($target->{$segment})) {
+ $target = $target->{$segment};
+ } else {
+ return value($default);
+ }
+ }
+
+ return $target;
+ }
+ }
+
+ if (! function_exists('tap')) {
+ /**
+ * Call the given Closure with the given value then return the value.
+ *
+ * @param mixed $value
+ * @param callable|null $callback
+ * @return mixed
+ */
+ function tap($value, $callback = null)
+ {
+ if (is_null($callback)) {
+ return new HigherOrderTapProxy($value);
+ }
+
+ $callback($value);
+
+ return $value;
+ }
+ }
+
+ if (! function_exists('with')) {
+ /**
+ * Return the given object. Useful for chaining.
+ *
+ * @param mixed $object
+ * @return mixed
+ */
+ function with($object)
+ {
+ return $object;
+ }
+ }
+
+ if (! function_exists('dd')) {
+ /**
+ * Dump the passed variables and end the script.
+ *
+ * @param mixed
+ * @return void
+ */
+ function dd(...$args)
+ {
+ foreach ($args as $x) {
+ VarDumper::dump($x);
+ }
+ die(1);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/prerequisites.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/prerequisites.inc.php
index 220c87c..0cbd05a 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/prerequisites.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/prerequisites.inc.php
@@ -67,6 +67,8 @@
$WebAuthn->addRootCertificates($_SERVER['DOCUMENT_ROOT'] . '/inc/lib/WebAuthn/rootCertificates/googleHardware.pem');
$WebAuthn->addRootCertificates($_SERVER['DOCUMENT_ROOT'] . '/inc/lib/WebAuthn/rootCertificates/microsoftTpmCollection.pem');
$WebAuthn->addRootCertificates($_SERVER['DOCUMENT_ROOT'] . '/inc/lib/WebAuthn/rootCertificates/huawei.pem');
+$WebAuthn->addRootCertificates($_SERVER['DOCUMENT_ROOT'] . '/inc/lib/WebAuthn/rootCertificates/trustkey.pem');
+$WebAuthn->addRootCertificates($_SERVER['DOCUMENT_ROOT'] . '/inc/lib/WebAuthn/rootCertificates/bsi.pem');
// Redis
$redis = new Redis();
@@ -170,29 +172,12 @@
set_exception_handler('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;
- }
+function get_remote_ip() {
$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;
- }
+ return $remote;
}
// Load core functions first
@@ -207,7 +192,7 @@
if (!isset($_SESSION['mailcow_locale']) && !isset($_COOKIE['mailcow_locale'])) {
if ($DETECT_LANGUAGE && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$header_lang = strtolower(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2));
- if (in_array($header_lang, $AVAILABLE_LANGUAGES)) {
+ if (array_key_exists($header_lang, $AVAILABLE_LANGUAGES)) {
$_SESSION['mailcow_locale'] = $header_lang;
}
}
@@ -218,7 +203,7 @@
if (isset($_COOKIE['mailcow_locale'])) {
(preg_match('/^[a-z]{2}$/', $_COOKIE['mailcow_locale'])) ? $_SESSION['mailcow_locale'] = $_COOKIE['mailcow_locale'] : setcookie("mailcow_locale", "", time() - 300);
}
-if (isset($_GET['lang']) && in_array($_GET['lang'], $AVAILABLE_LANGUAGES)) {
+if (isset($_GET['lang']) && array_key_exists($_GET['lang'], $AVAILABLE_LANGUAGES)) {
$_SESSION['mailcow_locale'] = $_GET['lang'];
setcookie("mailcow_locale", $_GET['lang'], time()+30758400); // one year
}
@@ -234,27 +219,27 @@
}
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.acl.inc.php';
-require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.app_passwd.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.admin.inc.php';
-require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quarantine.inc.php';
-require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quota_notification.inc.php';
-require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.policy.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.app_passwd.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.customize.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.dkim.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.docker.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.domain_admin.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fail2ban.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fwdhost.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailbox.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailq.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.oauth2.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.policy.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.presets.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.pushover.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quarantine.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quota_notification.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.ratelimit.inc.php';
-require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.transports.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.rspamd.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.tls_policy_maps.inc.php';
-require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fail2ban.inc.php';
-require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.docker.inc.php';
-require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.presets.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.transports.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/init_db.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.inc.php';
init_db_schema();
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/presets/rspamd/preset_1.yml b/mailcow/src/mailcow-dockerized/data/web/inc/presets/rspamd/preset_1.yml
index acbe352..41833cf 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/presets/rspamd/preset_1.yml
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/presets/rspamd/preset_1.yml
@@ -3,5 +3,5 @@
priority = 10;
authenticated = yes;
apply "default" {
- symbols_enabled = ["DKIM_SIGNED", "RATELIMITED", "RATELIMIT_UPDATE", "RATELIMIT_CHECK", "DYN_RL_CHECK", "HISTORY_SAVE", "MILTER_HEADERS", "ARC_SIGNED"];
+ symbols_enabled = ["BCC", "DKIM_SIGNED", "RATELIMITED", "RATELIMIT_UPDATE", "RATELIMIT_CHECK", "DYN_RL_CHECK", "HISTORY_SAVE", "MILTER_HEADERS", "ARC_SIGNED"];
}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/presets/rspamd/preset_4.yml b/mailcow/src/mailcow-dockerized/data/web/inc/presets/rspamd/preset_4.yml
new file mode 100644
index 0000000..c63071b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/presets/rspamd/preset_4.yml
@@ -0,0 +1,11 @@
+headline: lang.rsettings_preset_4
+content: |
+ priority = 10;
+ rcpt = "/.*@develcow.de$/";
+ from = "/.*/";
+ apply "default" {
+ MAILCOW_WHITE = -9999.0;
+ }
+ symbols [
+ "MAILCOW_WHITE"
+ ]
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/spf.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/spf.inc.php
index 199f572..55e164b 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/spf.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/spf.inc.php
@@ -1,8 +1,6 @@
<?php
error_reporting(0);
-
-function get_spf_allowed_hosts($check_domain)
-{
+function get_spf_allowed_hosts($check_domain, $expand_ipv6 = false) {
$hosts = array();
$records = dns_get_record($check_domain, DNS_TXT);
@@ -26,7 +24,7 @@
$mod = explode('=', $mech);
if ($mod[0] == 'redirect') // handle a redirect
{
- $hosts = get_spf_allowed_hosts($mod[1]);
+ $hosts = get_spf_allowed_hosts($mod[1],true);
return $hosts;
}
}
@@ -81,7 +79,13 @@
}
foreach ($hosts as &$host) {
if (filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
- $host = $host;
+ if ($expand_ipv6 === true) {
+ $hex = unpack("H*hex", inet_pton($host));
+ $host = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1);
+ }
+ else {
+ $host = $host;
+ }
}
}
return $hosts;
@@ -119,9 +123,8 @@
$hosts[] = $a_record['ip'];
}
$a_records = dns_get_record($domain, DNS_AAAA);
- foreach ($a_records as $a_record)
- {
- $hosts[] = $a_record['ipv6'];
+ foreach ($a_records as $a_record) {
+ $hosts[] = $a_record['ipv6'];
}
return $hosts;
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/triggers.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/triggers.inc.php
index 8785759..a2342df 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/triggers.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/triggers.inc.php
@@ -24,19 +24,16 @@
if ($as == "admin") {
$_SESSION['mailcow_cc_username'] = $login_user;
$_SESSION['mailcow_cc_role'] = "admin";
- $_SESSION['mailcow_cc_last_login'] = last_login($login_user);
header("Location: /admin");
}
elseif ($as == "domainadmin") {
$_SESSION['mailcow_cc_username'] = $login_user;
$_SESSION['mailcow_cc_role'] = "domainadmin";
- $_SESSION['mailcow_cc_last_login'] = last_login($login_user);
header("Location: /mailbox");
}
elseif ($as == "user") {
$_SESSION['mailcow_cc_username'] = $login_user;
$_SESSION['mailcow_cc_role'] = "user";
- $_SESSION['mailcow_cc_last_login'] = last_login($login_user);
$http_parameters = explode('&', $_SESSION['index_query_string']);
unset($_SESSION['index_query_string']);
if (in_array('mobileconfig', $http_parameters)) {
@@ -58,7 +55,7 @@
}
}
-if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['acl']['login_as'] == "1") {
+if (isset($_SESSION['mailcow_cc_role']) && (isset($_SESSION['acl']['login_as']) && $_SESSION['acl']['login_as'] == "1")) {
if (isset($_GET["duallogin"])) {
$duallogin = html_entity_decode(rawurldecode($_GET["duallogin"]));
if (filter_var($duallogin, FILTER_VALIDATE_EMAIL)) {
@@ -82,7 +79,7 @@
}
}
-if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "admin" || $_SESSION['mailcow_cc_role'] == "domainadmin")) {
+if (isset($_SESSION['mailcow_cc_role'])) {
if (isset($_POST["set_tfa"])) {
set_tfa($_POST);
}
@@ -93,7 +90,7 @@
fido2(array("action" => "unset_fido2_key", "post_data" => $_POST));
}
}
-if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin") {
+if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin" && !isset($_SESSION['mailcow_cc_api'])) {
// TODO: Move file upload to API?
if (isset($_POST["submit_main_logo"])) {
if ($_FILES['main_logo']['error'] == 0) {
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/vars.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/vars.inc.php
index f497ffb..91d2145 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/vars.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/vars.inc.php
@@ -45,21 +45,21 @@
// The autoconfig service will additionally announce the STARTTLS-enabled ports, specified in the "tlsport" variable.
'imap' => array(
'server' => $mailcow_hostname,
- 'port' => end(explode(':', getenv('IMAPS_PORT'))),
- 'tlsport' => end(explode(':', getenv('IMAP_PORT'))),
+ 'port' => (int)filter_var(substr(getenv('IMAPS_PORT'), strrpos(getenv('IMAPS_PORT'), ':')), FILTER_SANITIZE_NUMBER_INT),
+ 'tlsport' => (int)filter_var(substr(getenv('IMAP_PORT'), strrpos(getenv('IMAP_PORT'), ':')), FILTER_SANITIZE_NUMBER_INT)
),
'pop3' => array(
'server' => $mailcow_hostname,
- 'port' => end(explode(':', getenv('POPS_PORT'))),
- 'tlsport' => end(explode(':', getenv('POP_PORT'))),
+ 'port' => (int)filter_var(substr(getenv('POPS_PORT'), strrpos(getenv('POPS_PORT'), ':')), FILTER_SANITIZE_NUMBER_INT),
+ 'tlsport' => (int)filter_var(substr(getenv('POP_PORT'), strrpos(getenv('POP_PORT'), ':')), FILTER_SANITIZE_NUMBER_INT)
),
'smtp' => array(
'server' => $mailcow_hostname,
- 'port' => end(explode(':', getenv('SMTPS_PORT'))),
- 'tlsport' => end(explode(':', getenv('SUBMISSION_PORT'))),
+ 'port' => (int)filter_var(substr(getenv('SMTPS_PORT'), strrpos(getenv('SMTPS_PORT'), ':')), FILTER_SANITIZE_NUMBER_INT),
+ 'tlsport' => (int)filter_var(substr(getenv('SUBMISSION_PORT'), strrpos(getenv('SUBMISSION_PORT'), ':')), FILTER_SANITIZE_NUMBER_INT)
),
'activesync' => array(
- 'url' => 'https://'.$mailcow_hostname.($https_port == 443 ? '' : ':'.$https_port).'/Microsoft-Server-ActiveSync',
+ 'url' => 'https://' . $mailcow_hostname . ($https_port == 443 ? '' : ':' . $https_port) . '/Microsoft-Server-ActiveSync',
),
'caldav' => array(
'server' => $mailcow_hostname,
@@ -79,7 +79,29 @@
$DEFAULT_LANG = 'en';
// Available languages
-$AVAILABLE_LANGUAGES = array('ca', 'cs', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ko', 'lv', 'nl', 'pl', 'pt', 'ro', 'ru', 'sk', 'sv', 'zh');
+// https://www.iso.org/obp/ui/#search
+// https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
+$AVAILABLE_LANGUAGES = array(
+ 'cs' => 'Čeština (Czech)',
+ 'da' => 'Danish (Dansk)',
+ 'de' => 'Deutsch (German)',
+ 'en' => 'English',
+ 'es' => 'Español (Spanish)',
+ 'fi' => 'Suomi (Finish)',
+ 'fr' => 'Français (French)',
+ 'hu' => 'Magyar (Hungarian)',
+ 'it' => 'Italiano (Italian)',
+ 'ko' => '한국어 (Korean)',
+ 'lv' => 'latviešu (Latvian)',
+ 'nl' => 'Nederlands (Dutch)',
+ 'pl' => 'Język Polski (Polish)',
+ 'pt' => 'Português (Portuguese)',
+ 'ro' => 'Română (Romanian)',
+ 'ru' => 'Pусский (Russian)',
+ 'sk' => 'Slovenčina (Slovak)',
+ 'sv' => 'Svenska (Swedish)',
+ 'zh' => '中文 (Chinese)'
+);
// Change theme (default: lumen)
// Needs to be one of those: cerulean, cosmo, cyborg, darkly, flatly, journal, lumen, paper, readable, sandstone,
@@ -88,14 +110,6 @@
// WARNING: Only lumen is loaded locally. Enabling any other theme, will download external sources.
$DEFAULT_THEME = 'lumen';
-// Password complexity as regular expression
-// Min. 6 characters
-$PASSWD_REGEP = '.{6,}';
-// Min. 6 characters, which must include at least one uppercase letter, one lowercase letter and one number
-// $PASSWD_REGEP = '^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,}$';
-// Min. 6 characters, which must include at least one letter and one number
-// $PASSWD_REGEP = '^(?=.*[0-9])(?=.*[A-Za-z]).{6,}$';
-
// Show DKIM private keys - false by default
$SHOW_DKIM_PRIV_KEYS = false;
@@ -122,15 +136,9 @@
// Label for OTP devices
$OTP_LABEL = "mailcow UI";
-// Default "to" address in relay test tool
-$RELAY_TO = "null@hosted.mailcow.de";
-
// How long to wait (in s) for cURL Docker requests
$DOCKER_TIMEOUT = 60;
-// Anonymize IPs logged via UI
-$ANONYMIZE_IPS = true;
-
// Split DKIM key notation (bind format)
$SPLIT_DKIM_255 = false;
@@ -203,6 +211,7 @@
'Bad Words DE (only fired in combination with fishy TLDs)' => 'bad_words_de.map',
'Bad Languages' => 'bad_languages.map',
'Bulk Mail Headers' => 'bulk_header.map',
+ 'Bad (Junk) Mail Headers' => 'bad_header.map',
'Monitoring Hosts' => 'monitoring_nolog.map'
)
);