Compare commits

...
2 Commits
8 changed files with 185 additions and 27 deletions

No files matched your search

+31 -4
View File
@@ -287,23 +287,50 @@ touch /etc/asterisk/pjsip.conf \
/etc/asterisk/pjsip.custom.conf \ /etc/asterisk/pjsip.custom.conf \
/etc/asterisk/extensions.conf \ /etc/asterisk/extensions.conf \
/etc/asterisk/extensions.custom.conf \ /etc/asterisk/extensions.custom.conf \
/etc/asterisk/musiconhold.conf \
/etc/asterisk/musiconhold.custom.conf \ /etc/asterisk/musiconhold.custom.conf \
/etc/asterisk/voicemail.conf \
/etc/asterisk/voicemail.custom.conf \ /etc/asterisk/voicemail.custom.conf \
/etc/asterisk/modules.conf \
/etc/asterisk/rtp.conf \ /etc/asterisk/rtp.conf \
/etc/asterisk/features.conf /etc/asterisk/features.conf
# 1. Modules Asterisk : Désactivation des modules ODBC/IMAP incompatibles sur Debian (évite conflit bloquant app_voicemail)
if ! grep -q 'noload => app_voicemail_odbc.so' /etc/asterisk/modules.conf 2>/dev/null; then
if grep -q '\[modules\]' /etc/asterisk/modules.conf 2>/dev/null; then
sed -i '/\[modules\]/a noload => app_voicemail_odbc.so\nnoload => app_voicemail_imap.so' /etc/asterisk/modules.conf 2>/dev/null || true
else
printf '[modules]\nautoload=yes\nnoload => app_voicemail_odbc.so\nnoload => app_voicemail_imap.so\n' >> /etc/asterisk/modules.conf
fi
fi
# 2. Inclusions des fichiers custom dans les configurations principales
if ! grep -q 'pjsip.custom.conf' /etc/asterisk/pjsip.conf 2>/dev/null; then if ! grep -q 'pjsip.custom.conf' /etc/asterisk/pjsip.conf 2>/dev/null; then
printf '\n#tryinclude "pjsip.custom.conf"\n' >> /etc/asterisk/pjsip.conf printf '\n#tryinclude "pjsip.custom.conf"\n' >> /etc/asterisk/pjsip.conf
fi fi
if ! grep -q 'extensions.custom.conf' /etc/asterisk/extensions.conf 2>/dev/null; then if ! grep -q 'extensions.custom.conf' /etc/asterisk/extensions.conf 2>/dev/null; then
printf '\n#tryinclude "extensions.custom.conf"\n' >> /etc/asterisk/extensions.conf printf '\n#tryinclude "extensions.custom.conf"\n' >> /etc/asterisk/extensions.conf
fi fi
chown -R asterisk:asterisk /etc/asterisk if ! grep -q 'musiconhold.custom.conf' /etc/asterisk/musiconhold.conf 2>/dev/null; then
sed -i 's/^\[default\]/;[default]/' /etc/asterisk/musiconhold.conf 2>/dev/null || true
sed -i 's/^mode=files/;mode=files/' /etc/asterisk/musiconhold.conf 2>/dev/null || true
sed -i 's/^directory=moh/;directory=moh/' /etc/asterisk/musiconhold.conf 2>/dev/null || true
printf '\n#tryinclude "/etc/asterisk/musiconhold.custom.conf"\n' >> /etc/asterisk/musiconhold.conf
fi
if ! grep -q 'voicemail.custom.conf' /etc/asterisk/voicemail.conf 2>/dev/null; then
sed -i 's/^1234 => 4242/;1234 => 4242/' /etc/asterisk/voicemail.conf 2>/dev/null || true
sed -i 's/^;\s*passwordlocation\s*=\s*spooldir/passwordlocation=spooldir/' /etc/asterisk/voicemail.conf 2>/dev/null || true
sed -i 's|^;\s*externpassnotify\s*=.*|externpassnotify=/usr/bin/php /var/www/nexus-pbx/scripts/voicemail_pass_sync.php|' /etc/asterisk/voicemail.conf 2>/dev/null || true
printf '\n#tryinclude "voicemail.custom.conf"\n' >> /etc/asterisk/voicemail.conf
fi
mkdir -p /var/spool/asterisk/voicemail/default /var/lib/asterisk/sounds/custom /var/lib/asterisk/moh
chown -R asterisk:asterisk /etc/asterisk /var/spool/asterisk /var/lib/asterisk
chmod 0664 /etc/asterisk/*.conf /etc/asterisk/*.custom.conf 2>/dev/null || true chmod 0664 /etc/asterisk/*.conf /etc/asterisk/*.custom.conf 2>/dev/null || true
chmod 2750 /etc/asterisk/keys chmod 2750 /etc/asterisk/keys
chmod 2775 /etc/asterisk chmod 2775 /etc/asterisk /var/spool/asterisk /var/spool/asterisk/voicemail /var/lib/asterisk/sounds /var/lib/asterisk/moh
setfacl -R -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk 2>/dev/null || true setfacl -R -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk /var/spool/asterisk /var/lib/asterisk 2>/dev/null || true
setfacl -R -d -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk 2>/dev/null || true setfacl -R -d -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk /var/spool/asterisk /var/lib/asterisk 2>/dev/null || true
# Rechargement Asterisk immédiat pour appliquer AMI et Logger # Rechargement Asterisk immédiat pour appliquer AMI et Logger
asterisk -rx "core reload" 2>/dev/null || true asterisk -rx "core reload" 2>/dev/null || true
+2 -2
View File
@@ -140,7 +140,7 @@ try {
$installedVerData = file_exists("{$appDir}/version.json") $installedVerData = file_exists("{$appDir}/version.json")
? json_decode((string)file_get_contents("{$appDir}/version.json"), true) ? json_decode((string)file_get_contents("{$appDir}/version.json"), true)
: []; : [];
$installedVer = $installedVerData['version'] ?? '1.4.5'; $installedVer = $installedVerData['version'] ?? '1.4.7';
echo json_encode([ echo json_encode([
'success' => true, 'success' => true,
@@ -227,7 +227,7 @@ try {
@chmod($webLog, 0664); @chmod($webLog, 0664);
} }
@unlink('/tmp/nexus_fw_status_cache.json'); @unlink('/tmp/nexus_fw_status_cache.json');
exec('sudo /usr/bin/fail2ban-client reload 2>&1'); exec('sudo /usr/bin/systemctl restart fail2ban 2>&1 || sudo /usr/bin/fail2ban-client reload 2>&1');
echo json_encode([ echo json_encode([
'success' => true, 'success' => true,
+1 -1
View File
@@ -18,7 +18,7 @@ $companyLogo = trim($branding['company_logo'] ?? '');
$hasBranding = !empty($companyName) || !empty($companyLogo); $hasBranding = !empty($companyName) || !empty($companyLogo);
$appVerData = file_exists(__DIR__ . '/../version.json') ? json_decode((string)file_get_contents(__DIR__ . '/../version.json'), true) : []; $appVerData = file_exists(__DIR__ . '/../version.json') ? json_decode((string)file_get_contents(__DIR__ . '/../version.json'), true) : [];
$appVersion = $appVerData['version'] ?? '1.4.5'; $appVersion = $appVerData['version'] ?? '1.4.7';
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="fr" class="h-full"> <html lang="fr" class="h-full">
+34 -2
View File
@@ -65,15 +65,47 @@ touch /etc/asterisk/pjsip.conf \
/etc/asterisk/pjsip.custom.conf \ /etc/asterisk/pjsip.custom.conf \
/etc/asterisk/extensions.conf \ /etc/asterisk/extensions.conf \
/etc/asterisk/extensions.custom.conf \ /etc/asterisk/extensions.custom.conf \
/etc/asterisk/musiconhold.conf \
/etc/asterisk/musiconhold.custom.conf \ /etc/asterisk/musiconhold.custom.conf \
/etc/asterisk/voicemail.conf \
/etc/asterisk/voicemail.custom.conf \ /etc/asterisk/voicemail.custom.conf \
/etc/asterisk/modules.conf \
/etc/asterisk/rtp.conf \ /etc/asterisk/rtp.conf \
/etc/asterisk/features.conf 2>/dev/null || true /etc/asterisk/features.conf 2>/dev/null || true
mkdir -p /var/lib/asterisk/sounds/custom /var/lib/asterisk/moh /var/spool/asterisk/voicemail 2>/dev/null || true # Désactivation des modules ODBC/IMAP incompatibles sur Debian (évite conflit bloquant app_voicemail)
if ! grep -q 'noload => app_voicemail_odbc.so' /etc/asterisk/modules.conf 2>/dev/null; then
if grep -q '\[modules\]' /etc/asterisk/modules.conf 2>/dev/null; then
sed -i '/\[modules\]/a noload => app_voicemail_odbc.so\nnoload => app_voicemail_imap.so' /etc/asterisk/modules.conf 2>/dev/null || true
else
printf '[modules]\nautoload=yes\nnoload => app_voicemail_odbc.so\nnoload => app_voicemail_imap.so\n' >> /etc/asterisk/modules.conf
fi
fi
# Inclusions Asterisk et configuration messagerie vocale
if ! grep -q 'pjsip.custom.conf' /etc/asterisk/pjsip.conf 2>/dev/null; then
printf '\n#tryinclude "pjsip.custom.conf"\n' >> /etc/asterisk/pjsip.conf
fi
if ! grep -q 'extensions.custom.conf' /etc/asterisk/extensions.conf 2>/dev/null; then
printf '\n#tryinclude "extensions.custom.conf"\n' >> /etc/asterisk/extensions.conf
fi
if ! grep -q 'musiconhold.custom.conf' /etc/asterisk/musiconhold.conf 2>/dev/null; then
sed -i 's/^\[default\]/;[default]/' /etc/asterisk/musiconhold.conf 2>/dev/null || true
sed -i 's/^mode=files/;mode=files/' /etc/asterisk/musiconhold.conf 2>/dev/null || true
sed -i 's/^directory=moh/;directory=moh/' /etc/asterisk/musiconhold.conf 2>/dev/null || true
printf '\n#tryinclude "/etc/asterisk/musiconhold.custom.conf"\n' >> /etc/asterisk/musiconhold.conf
fi
if ! grep -q 'voicemail.custom.conf' /etc/asterisk/voicemail.conf 2>/dev/null; then
sed -i 's/^1234 => 4242/;1234 => 4242/' /etc/asterisk/voicemail.conf 2>/dev/null || true
sed -i 's/^;\s*passwordlocation\s*=\s*spooldir/passwordlocation=spooldir/' /etc/asterisk/voicemail.conf 2>/dev/null || true
sed -i 's|^;\s*externpassnotify\s*=.*|externpassnotify=/usr/bin/php /var/www/nexus-pbx/scripts/voicemail_pass_sync.php|' /etc/asterisk/voicemail.conf 2>/dev/null || true
printf '\n#tryinclude "voicemail.custom.conf"\n' >> /etc/asterisk/voicemail.conf
fi
mkdir -p /var/lib/asterisk/sounds/custom /var/lib/asterisk/moh /var/spool/asterisk/voicemail/default 2>/dev/null || true
chown -R asterisk:asterisk /etc/asterisk /var/lib/asterisk /var/spool/asterisk /var/log/asterisk 2>/dev/null || true chown -R asterisk:asterisk /etc/asterisk /var/lib/asterisk /var/spool/asterisk /var/log/asterisk 2>/dev/null || true
chmod -R 775 /etc/asterisk /var/lib/asterisk/sounds /var/lib/asterisk/moh /var/spool/asterisk 2>/dev/null || true chmod -R 775 /etc/asterisk /var/lib/asterisk/sounds /var/lib/asterisk/moh /var/spool/asterisk 2>/dev/null || true
chmod 2775 /etc/asterisk /var/lib/asterisk/sounds /var/lib/asterisk/sounds/custom /var/lib/asterisk/moh /var/spool/asterisk 2>/dev/null || true chmod 2775 /etc/asterisk /var/lib/asterisk/sounds /var/lib/asterisk/sounds/custom /var/lib/asterisk/moh /var/spool/asterisk /var/spool/asterisk/voicemail 2>/dev/null || true
chmod 2750 /etc/asterisk/keys 2>/dev/null || true chmod 2750 /etc/asterisk/keys 2>/dev/null || true
chmod 0664 /etc/asterisk/*.conf /etc/asterisk/*.custom.conf 2>/dev/null || true chmod 0664 /etc/asterisk/*.conf /etc/asterisk/*.custom.conf 2>/dev/null || true
+10 -2
View File
@@ -130,8 +130,16 @@ $gen->writeAllConfigs();
# 5. Fix permissions & ACLs # 5. Fix permissions & ACLs
echo -e "${C_GRAY}[5/6] Application des permissions et ACLs système...${C_RESET}" echo -e "${C_GRAY}[5/6] Application des permissions et ACLs système...${C_RESET}"
setfacl -R -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk /var/lib/asterisk/sounds /var/lib/asterisk/moh 2>/dev/null || true php -r '
setfacl -R -d -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk /var/lib/asterisk/sounds /var/lib/asterisk/moh 2>/dev/null || true require_once "/var/www/nexus-pbx/src/Database.php";
require_once "/var/www/nexus-pbx/src/SystemChecker.php";
App\SystemChecker::ensureAsteriskIncludes();
' 2>/dev/null || true
mkdir -p /var/spool/asterisk/voicemail/default /var/lib/asterisk/sounds/custom /var/lib/asterisk/moh 2>/dev/null || true
chown -R asterisk:asterisk /var/spool/asterisk /var/lib/asterisk/sounds /var/lib/asterisk/moh 2>/dev/null || true
chmod 2775 /var/spool/asterisk /var/spool/asterisk/voicemail /var/lib/asterisk/sounds /var/lib/asterisk/moh 2>/dev/null || true
setfacl -R -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk /var/lib/asterisk/sounds /var/lib/asterisk/moh /var/spool/asterisk 2>/dev/null || true
setfacl -R -d -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk /var/lib/asterisk/sounds /var/lib/asterisk/moh /var/spool/asterisk 2>/dev/null || true
chmod 0664 /etc/asterisk/*.conf /etc/asterisk/*.custom.conf 2>/dev/null || true chmod 0664 /etc/asterisk/*.conf /etc/asterisk/*.custom.conf 2>/dev/null || true
# 6. Rechargement des services # 6. Rechargement des services
+66 -7
View File
@@ -70,17 +70,22 @@ class SystemChecker
: 'Accès refusé en écriture dans /etc/asterisk pour PHP-FPM', : 'Accès refusé en écriture dans /etc/asterisk pour PHP-FPM',
]; ];
// 5. Directives #tryinclude dans pjsip.conf et extensions.conf // 5. Directives #tryinclude dans pjsip.conf, extensions.conf, voicemail.conf et modules.conf
$pjsipMain = @file_get_contents('/etc/asterisk/pjsip.conf') ?: ''; $pjsipMain = @file_get_contents('/etc/asterisk/pjsip.conf') ?: '';
$extMain = @file_get_contents('/etc/asterisk/extensions.conf') ?: ''; $extMain = @file_get_contents('/etc/asterisk/extensions.conf') ?: '';
$incOk = str_contains($pjsipMain, 'pjsip.custom.conf') && str_contains($extMain, 'extensions.custom.conf'); $vmMain = @file_get_contents('/etc/asterisk/voicemail.conf') ?: '';
$modMain = @file_get_contents('/etc/asterisk/modules.conf') ?: '';
$incOk = str_contains($pjsipMain, 'pjsip.custom.conf')
&& str_contains($extMain, 'extensions.custom.conf')
&& str_contains($vmMain, 'voicemail.custom.conf')
&& str_contains($modMain, 'app_voicemail_odbc.so');
$checks[] = [ $checks[] = [
'id' => 'asterisk_includes', 'id' => 'asterisk_includes',
'label' => 'Inclusions natives (#tryinclude *.custom.conf)', 'label' => 'Inclusions Asterisk & Voicemail (#tryinclude & modules.conf)',
'ok' => $incOk, 'ok' => $incOk,
'detail' => $incOk 'detail' => $incOk
? 'pjsip.conf et extensions.conf incluent bien les fichiers .custom.conf' ? 'pjsip.conf, extensions.conf, voicemail.conf et modules.conf configurés'
: 'Directive #tryinclude manquante dans pjsip.conf ou extensions.conf', : 'Directive #tryinclude manquante ou conflit modules.conf détecté',
]; ];
// 6. Certificats TLS (Let's Encrypt ou Certificat local Debian) // 6. Certificats TLS (Let's Encrypt ou Certificat local Debian)
@@ -142,6 +147,25 @@ class SystemChecker
public static function ensureAsteriskIncludes(): void public static function ensureAsteriskIncludes(): void
{ {
// 1. modules.conf: Désactiver les modules voicemail ODBC/IMAP incompatibles sur Debian (évite collision bloquante avec app_voicemail.so)
$modConf = '/etc/asterisk/modules.conf';
if (is_file($modConf) && is_writable($modConf)) {
$content = (string)file_get_contents($modConf);
$changed = false;
if (!str_contains($content, 'app_voicemail_odbc.so')) {
if (preg_match('/\[modules\]/i', $content)) {
$content = preg_replace('/\[modules\]/i', "[modules]\nnoload => app_voicemail_odbc.so\nnoload => app_voicemail_imap.so", $content, 1);
$changed = true;
} else {
$content = "[modules]\nautoload=yes\nnoload => app_voicemail_odbc.so\nnoload => app_voicemail_imap.so\n\n" . $content;
$changed = true;
}
}
if ($changed) {
file_put_contents($modConf, $content);
}
}
$pjsipConf = '/etc/asterisk/pjsip.conf'; $pjsipConf = '/etc/asterisk/pjsip.conf';
if (is_file($pjsipConf) && is_writable($pjsipConf)) { if (is_file($pjsipConf) && is_writable($pjsipConf)) {
$content = (string)file_get_contents($pjsipConf); $content = (string)file_get_contents($pjsipConf);
@@ -177,8 +201,20 @@ class SystemChecker
if (is_file($vmConf) && is_writable($vmConf)) { if (is_file($vmConf) && is_writable($vmConf)) {
$content = (string)file_get_contents($vmConf); $content = (string)file_get_contents($vmConf);
$cleaned = preg_replace('/^1234 => 4242.*/m', ';1234 => 4242,Example Mailbox,root@localhost', $content); $cleaned = preg_replace('/^1234 => 4242.*/m', ';1234 => 4242,Example Mailbox,root@localhost', $content);
$cleaned = preg_replace('/^;\s*passwordlocation\s*=\s*spooldir/m', 'passwordlocation=spooldir', $cleaned); if (preg_match('/^;\s*passwordlocation\s*=\s*spooldir/m', $cleaned)) {
$cleaned = preg_replace('/^;\s*externpassnotify\s*=.*/m', 'externpassnotify=/usr/bin/php /var/www/nexus-pbx/scripts/voicemail_pass_sync.php', $cleaned); $cleaned = preg_replace('/^;\s*passwordlocation\s*=\s*spooldir/m', 'passwordlocation=spooldir', $cleaned);
} elseif (!str_contains($cleaned, 'passwordlocation=spooldir') && !str_contains($cleaned, 'passwordlocation = spooldir')) {
if (preg_match('/\[general\]/i', $cleaned)) {
$cleaned = preg_replace('/\[general\]/i', "[general]\npasswordlocation=spooldir", $cleaned, 1);
}
}
if (preg_match('/^;\s*externpassnotify\s*=.*/m', $cleaned)) {
$cleaned = preg_replace('/^;\s*externpassnotify\s*=.*/m', 'externpassnotify=/usr/bin/php /var/www/nexus-pbx/scripts/voicemail_pass_sync.php', $cleaned);
} elseif (!str_contains($cleaned, 'externpassnotify=')) {
if (preg_match('/\[general\]/i', $cleaned)) {
$cleaned = preg_replace('/\[general\]/i', "[general]\nexternpassnotify=/usr/bin/php /var/www/nexus-pbx/scripts/voicemail_pass_sync.php", $cleaned, 1);
}
}
if (!str_contains($cleaned, 'voicemail.custom.conf')) { if (!str_contains($cleaned, 'voicemail.custom.conf')) {
$cleaned = rtrim($cleaned) . "\n\n#tryinclude \"voicemail.custom.conf\"\n"; $cleaned = rtrim($cleaned) . "\n\n#tryinclude \"voicemail.custom.conf\"\n";
} }
@@ -187,6 +223,29 @@ class SystemChecker
} }
} }
@mkdir('/var/spool/asterisk/voicemail/default', 0775, true);
// Synchroniser manager.conf avec le mot de passe AMI de la base SQLite si nécessaire (ex: après restauration de backup)
$mgrConf = '/etc/asterisk/manager.conf';
if (is_file($mgrConf) && is_writable($mgrConf)) {
try {
$db = Database::getConnection();
$st = $db->query('SELECT ami_user, ami_secret FROM settings WHERE id = 1')->fetch();
if (!empty($st['ami_secret'])) {
$sec = trim((string)$st['ami_secret']);
$usr = trim((string)($st['ami_user'] ?? 'pbxgui')) ?: 'pbxgui';
$content = (string)file_get_contents($mgrConf);
if (str_contains($content, "[{$usr}]")) {
$updated = preg_replace("/(\[{$usr}\][^\[]*secret\s*=\s*)([^\r\n]+)/i", "\${1}{$sec}", $content);
if ($updated !== null && $updated !== $content) {
file_put_contents($mgrConf, $updated);
@exec('asterisk -rx "manager reload" 2>/dev/null || true');
}
}
}
} catch (\Throwable) {}
}
$astConf = '/etc/asterisk/asterisk.conf'; $astConf = '/etc/asterisk/asterisk.conf';
if (is_file($astConf) && is_writable($astConf)) { if (is_file($astConf) && is_writable($astConf)) {
$content = (string)file_get_contents($astConf); $content = (string)file_get_contents($astConf);
+36 -4
View File
@@ -298,17 +298,19 @@ class SystemMetrics
} }
} }
$seenExts = [];
foreach (preg_split('/\r?\n/', $rawContacts) ?: [] as $line) { foreach (preg_split('/\r?\n/', $rawContacts) ?: [] as $line) {
// Contact: 101/sip:101@10.10.167.162:5060 5dd9a21be8 Avail 9.234 // Supporte sip:, sips:, sans préfixe, tous types de hash et RTT (numérique, nan, N/A ou absent)
// or with -nan: Contact: 102/sip:102@10.10.168.228:5060;x-ast-txp=trans bb0686ce80 Unavail -nan if (preg_match('/Contact:\s+([^\s\/]+)\/(?:sips?:)?([^\s]+)\s+([a-zA-Z0-9]+)\s+(\S+)(?:\s+(\S+))?/i', $line, $m)) {
if (preg_match('/Contact:\s+([^\s\/]+)\/sip:([^\s]+)\s+([a-f0-9]+)\s+(\S+)\s+(-?[0-9.]+|nan|-nan)/i', $line, $m)) {
$extNum = $m[1]; $extNum = $m[1];
$uri = $m[2]; $uri = $m[2];
$status = $m[4]; $status = $m[4];
$rttRaw = $m[5] ?? null;
$isAvail = (stripos($status, 'Avail') !== false && stripos($status, 'Unavail') === false) || stripos($status, 'NonQual') !== false; $isAvail = (stripos($status, 'Avail') !== false && stripos($status, 'Unavail') === false) || stripos($status, 'NonQual') !== false;
if ($isAvail) { if ($isAvail) {
$onlineCount++; $onlineCount++;
} }
$seenExts[$extNum] = true;
$meta = $contactMeta[$extNum] ?? []; $meta = $contactMeta[$extNum] ?? [];
$fullUri = $meta['uri'] ?? ("sip:" . $uri); $fullUri = $meta['uri'] ?? ("sip:" . $uri);
@@ -330,7 +332,37 @@ class SystemMetrics
'user_agent' => $userAgent, 'user_agent' => $userAgent,
'active_transport' => $activeTransport, 'active_transport' => $activeTransport,
'status' => $status, 'status' => $status,
'rtt_ms' => is_numeric($m[5]) ? round((float)$m[5], 1) : null, 'rtt_ms' => ($rttRaw !== null && is_numeric($rttRaw)) ? round((float)$rttRaw, 1) : null,
];
}
}
// Filet de sécurité 100% infaillible : Tous les contacts enregistrés dans AstDB (/registrar/contact)
// non encore répertoriés (par exemple si qualify est désactivé ou RTT non disponible)
$nowTime = time();
foreach ($contactMeta as $extNum => $meta) {
if (isset($seenExts[$extNum])) {
continue;
}
$exp = (int)($meta['expiration_time'] ?? 0);
if ($exp === 0 || $exp > $nowTime) {
$onlineCount++;
$fullUri = $meta['uri'] ?? '';
$activeTransport = 'udp';
if (preg_match('/transport=(tls|wss|ws|tcp|udp)/i', $fullUri, $tm)) {
$activeTransport = strtolower($tm[1]);
} elseif (preg_match('/x-ast-txp=transport-(tls|wss|ws|tcp|udp)/i', $fullUri, $tm)) {
$activeTransport = strtolower($tm[1]);
} elseif (str_starts_with($fullUri, 'sips:')) {
$activeTransport = 'tls';
}
$contacts[] = [
'extension' => (string)$extNum,
'uri' => $fullUri,
'user_agent' => $meta['user_agent'] ?? '',
'active_transport' => $activeTransport,
'status' => 'Avail',
'rtt_ms' => null,
]; ];
} }
} }
+5 -5
View File
@@ -1,12 +1,12 @@
{ {
"version": "1.4.5", "version": "1.4.7",
"codename": "Helios", "codename": "Helios",
"release_date": "2026-11-04", "release_date": "2026-11-04",
"min_php_version": "8.2", "min_php_version": "8.2",
"changelog": [ "changelog": [
"Application instantanée des mots de passe SIP et configurations des postes dans Asterisk (rechargement PJSIP en temps réel)", "Détection ultra-robuste de l'état des téléphones IP (support SIPS, statuts sans qualify et fallback infaillible AstDB)",
"Suppression du délai d'application sur les postes, groupes de sonnerie et groupes de téléavertissement", "Réinitialisation immédiate du compteur d'attaques contrées Fail2ban lors du vidage du journal de sécurité",
"Fiabilisation maximale de la mise à jour (rechargement web asynchrone non-bloquant et gestion d'erreurs tolérante)", "Synchronisation automatique des identifiants AMI (/etc/asterisk/manager.conf) après restauration d'une sauvegarde",
"Nouvelle boîte modale élégante et personnalisée pour confirmer le lancement des mises à jour" "Correction et fiabilisation de la messagerie vocale (*97 / *98) sur toute installation fraîche Debian"
] ]
} }