PDO::ERRMODE_EXCEPTION]); } return $pdo; } // ===================================================== // CLOUDFLARE API // ===================================================== class CloudflareAPI { private $email; private $apiKey; private $apiToken; private $baseUrl = 'https://api.cloudflare.com/client/v4'; public function __construct($accountId) { $pdo = getDB(); $stmt = $pdo->prepare("SELECT * FROM admin.cloudflare_accounts WHERE id = ?"); $stmt->execute([$accountId]); $account = $stmt->fetch(PDO::FETCH_ASSOC); $this->email = $account['email'] ?? ''; $this->apiKey = $account['api_key'] ?? ''; $this->apiToken = $account['api_token'] ?? ''; } private function request($endpoint, $method = 'GET', $data = null) { $ch = curl_init($this->baseUrl . $endpoint); $headers = ['Content-Type: application/json']; if ($this->apiToken) { $headers[] = 'Authorization: Bearer ' . $this->apiToken; } else { $headers[] = 'X-Auth-Email: ' . $this->email; $headers[] = 'X-Auth-Key: ' . $this->apiKey; } curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_TIMEOUT => 30 ]); if ($data && in_array($method, ['POST', 'PUT', 'PATCH'])) { curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); } $response = curl_exec($ch); $error = curl_error($ch); curl_close($ch); if ($error) { return ['success' => false, 'errors' => [['message' => $error]]]; } return json_decode($response, true); } public function getZoneId($domain) { // Extraire le domaine racine $parts = explode('.', $domain); $rootDomain = implode('.', array_slice($parts, -2)); $result = $this->request('/zones?name=' . $rootDomain); if ($result['success'] && !empty($result['result'])) { return $result['result'][0]['id']; } return null; } public function createRecord($zoneId, $type, $name, $content, $ttl = 1, $proxied = false) { return $this->request("/zones/$zoneId/dns_records", 'POST', [ 'type' => $type, 'name' => $name, 'content' => $content, 'ttl' => $ttl, 'proxied' => $proxied ]); } public function listRecords($zoneId, $type = null, $name = null) { $params = []; if ($type) $params[] = "type=$type"; if ($name) $params[] = "name=$name"; $query = $params ? '?' . implode('&', $params) : ''; return $this->request("/zones/$zoneId/dns_records$query"); } public function deleteRecord($zoneId, $recordId) { return $this->request("/zones/$zoneId/dns_records/$recordId", 'DELETE'); } public function pushDNSRecords($domain, $records) { $results = []; $zoneId = $this->getZoneId($domain); if (!$zoneId) { return ['success' => false, 'error' => 'Zone not found for domain: ' . $domain]; } foreach ($records as $record) { $name = $record['name'] === '@' ? $domain : $record['name'] . '.' . $domain; // Vérifier si le record existe déjà $existing = $this->listRecords($zoneId, $record['type'], $name); if (!empty($existing['result'])) { // Supprimer l'ancien foreach ($existing['result'] as $old) { $this->deleteRecord($zoneId, $old['id']); } } // Créer le nouveau $result = $this->createRecord( $zoneId, $record['type'], $name, $record['content'], $record['ttl'] ?? 1, $record['proxied'] ?? false ); $results[] = [ 'record' => $record['type'] . ' ' . $record['name'], 'success' => $result['success'] ?? false, 'id' => $result['result']['id'] ?? null, 'error' => $result['errors'][0]['message'] ?? null ]; } return ['success' => true, 'results' => $results]; } } // ===================================================== // FREEDNS API (via scraping) // ===================================================== class FreeDNSAPI { private $cookie; private $accountId; private $baseUrl = 'https://freedns.afraid.org'; public function __construct($accountId) { $this->accountId = $accountId; $pdo = getDB(); $stmt = $pdo->prepare("SELECT * FROM admin.freedns_accounts WHERE id = ?"); $stmt->execute([$accountId]); $account = $stmt->fetch(PDO::FETCH_ASSOC); $this->cookie = $account['cookie'] ?? ''; } public function login($username, $password) { $ch = curl_init($this->baseUrl . '/zc.php?action=auth'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'username' => $username, 'password' => $password, 'submit' => 'Login' ]), CURLOPT_HEADER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_USERAGENT => 'Mozilla/5.0' ]); $response = curl_exec($ch); curl_close($ch); preg_match_all('/Set-Cookie:\s*([^;]+)/', $response, $matches); $this->cookie = implode('; ', $matches[1] ?? []); if (strpos($this->cookie, 'dns_cookie') !== false) { // Sauvegarder le cookie $pdo = getDB(); $stmt = $pdo->prepare("UPDATE admin.freedns_accounts SET cookie = ?, last_login = NOW() WHERE id = ?"); $stmt->execute([$this->cookie, $this->accountId]); return ['success' => true]; } return ['success' => false, 'error' => 'Login failed']; } public function addRecord($subdomain, $baseDomain, $type, $value) { // Cette fonction nécessite le scraping de FreeDNS // Implémentation simplifiée return ['success' => false, 'error' => 'FreeDNS requires manual configuration']; } } // ===================================================== // NAMECHEAP API // ===================================================== class NamecheapAPI { private $apiUser; private $apiKey; private $username; private $clientIP; private $baseUrl = 'https://api.namecheap.com/xml.response'; public function __construct($accountId) { $pdo = getDB(); $stmt = $pdo->prepare("SELECT * FROM admin.namecheap_accounts WHERE id = ?"); $stmt->execute([$accountId]); $account = $stmt->fetch(PDO::FETCH_ASSOC); $this->apiUser = $account['api_user'] ?? $account['username']; $this->apiKey = $account['api_key'] ?? ''; $this->username = $account['username'] ?? ''; $this->clientIP = $account['client_ip'] ?? $_SERVER['SERVER_ADDR']; } private function request($command, $params = []) { $defaultParams = [ 'ApiUser' => $this->apiUser, 'ApiKey' => $this->apiKey, 'UserName' => $this->username, 'ClientIp' => $this->clientIP, 'Command' => $command ]; $allParams = array_merge($defaultParams, $params); $url = $this->baseUrl . '?' . http_build_query($allParams); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30 ]); $response = curl_exec($ch); curl_close($ch); return simplexml_load_string($response); } public function getDomains() { return $this->request('namecheap.domains.getList'); } public function getHosts($sld, $tld) { return $this->request('namecheap.domains.dns.getHosts', [ 'SLD' => $sld, 'TLD' => $tld ]); } public function setHosts($sld, $tld, $records) { $params = [ 'SLD' => $sld, 'TLD' => $tld ]; $i = 1; foreach ($records as $record) { $params["HostName$i"] = $record['name']; $params["RecordType$i"] = $record['type']; $params["Address$i"] = $record['content']; $params["TTL$i"] = $record['ttl'] ?? 1800; $i++; } return $this->request('namecheap.domains.dns.setHosts', $params); } public function pushDNSRecords($domain, $records) { $parts = explode('.', $domain); $tld = array_pop($parts); $sld = array_pop($parts); // Récupérer les records existants $existing = $this->getHosts($sld, $tld); // Fusionner avec les nouveaux $allRecords = []; // Garder les existants qui ne sont pas remplacés if (isset($existing->CommandResponse->DomainDNSGetHostsResult->host)) { foreach ($existing->CommandResponse->DomainDNSGetHostsResult->host as $host) { $allRecords[] = [ 'name' => (string)$host['Name'], 'type' => (string)$host['Type'], 'content' => (string)$host['Address'], 'ttl' => (int)$host['TTL'] ]; } } // Ajouter/remplacer les nouveaux foreach ($records as $newRecord) { $found = false; foreach ($allRecords as &$existing) { if ($existing['name'] === $newRecord['name'] && $existing['type'] === $newRecord['type']) { $existing['content'] = $newRecord['content']; $found = true; break; } } if (!$found) { $allRecords[] = $newRecord; } } $result = $this->setHosts($sld, $tld, $allRecords); return [ 'success' => (string)$result['Status'] === 'OK', 'results' => $allRecords ]; } } // ===================================================== // MAIN API HANDLER // ===================================================== function getDNSRecordsFromDB($domainId) { $pdo = getDB(); // Récupérer le domaine $stmt = $pdo->prepare("SELECT domain FROM admin.domains_pool WHERE id = ?"); $stmt->execute([$domainId]); $domain = $stmt->fetchColumn(); if (!$domain) { return ['error' => 'Domain not found']; } // Récupérer les IPs MTA actives $stmt = $pdo->query("SELECT main_ip FROM admin.mta_servers WHERE status = 'Activated' AND main_ip IS NOT NULL LIMIT 5"); $ips = $stmt->fetchAll(PDO::FETCH_COLUMN); if (empty($ips)) { $ips = ['176.52.128.44', '119.8.153.154', '101.44.3.125']; } // Générer les records via la fonction SQL $ipArray = "ARRAY['" . implode("','", $ips) . "']"; $stmt = $pdo->query("SELECT * FROM admin.generate_dns_records('$domain', $ipArray)"); $records = $stmt->fetchAll(PDO::FETCH_ASSOC); // Convertir au format API $formatted = []; foreach ($records as $r) { $formatted[] = [ 'type' => $r['record_type'], 'name' => $r['record_name'], 'content' => $r['record_value'], 'ttl' => 1 ]; } return ['domain' => $domain, 'records' => $formatted, 'mta_ips' => $ips]; } function pushDNS($domainId, $provider, $providerAccountId) { $dnsData = getDNSRecordsFromDB($domainId); if (isset($dnsData['error'])) { return $dnsData; } switch ($provider) { case 'cloudflare': $api = new CloudflareAPI($providerAccountId); return $api->pushDNSRecords($dnsData['domain'], $dnsData['records']); case 'namecheap': $api = new NamecheapAPI($providerAccountId); return $api->pushDNSRecords($dnsData['domain'], $dnsData['records']); case 'freedns': return ['success' => false, 'error' => 'FreeDNS requires manual configuration via web interface']; default: return ['success' => false, 'error' => 'Unknown provider: ' . $provider]; } } // Handle request $action = $_REQUEST['action'] ?? 'status'; $domainId = $_REQUEST['domain_id'] ?? null; $provider = $_REQUEST['provider'] ?? 'cloudflare'; $providerAccountId = $_REQUEST['provider_account_id'] ?? 1; switch ($action) { case 'generate': // Juste générer les records sans pousser echo json_encode(getDNSRecordsFromDB($domainId)); break; case 'push': // Générer et pousser vers le provider echo json_encode(pushDNS($domainId, $provider, $providerAccountId)); break; case 'status': default: echo json_encode([ 'status' => 'ok', 'endpoints' => [ 'generate' => '?action=generate&domain_id=123', 'push' => '?action=push&domain_id=123&provider=cloudflare&provider_account_id=1' ], 'providers' => ['cloudflare', 'namecheap', 'freedns'] ]); }