diff --git a/ajax/adblock/update_blocklist.php b/ajax/adblock/update_blocklist.php index f21ed4cd..458369ab 100644 --- a/ajax/adblock/update_blocklist.php +++ b/ajax/adblock/update_blocklist.php @@ -5,50 +5,57 @@ require_once '../../includes/session.php'; require_once '../../includes/config.php'; require_once '../../includes/authenticate.php'; +define('BLOCKLISTS_FILE', __DIR__ . '/../../config/blocklists.json'); + if (isset($_POST['blocklist_id'])) { - $blocklist_id = escapeshellcmd($_POST['blocklist_id']); + $blocklist_id = $_POST['blocklist_id']; + $json = file_get_contents(BLOCKLISTS_FILE); + $allLists = json_decode($json, true); - switch ($blocklist_id) { - case "StevenBlack/hosts \(default\)": - $list_url = "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"; - $dest_file = "hostnames.txt"; - break; - case "badmojr/1Hosts \(Mini\)": - $list_url = "https://badmojr.github.io/1Hosts/mini/hosts.txt"; - $dest_file = "hostnames.txt"; - break; - case "badmojr/1Hosts \(Lite\)": - $list_url = "https://badmojr.github.io/1Hosts/Lite/hosts.txt"; - $dest_file = "hostnames.txt"; - break; - case "badmojr/1Hosts \(Pro\)": - $list_url = "https://badmojr.github.io/1Hosts/Pro/hosts.txt"; - $dest_file = "hostnames.txt"; - break; - case "badmojr/1Hosts \(Xtra\)": - $list_url = "https://badmojr.github.io/1Hosts/Xtra/hosts.txt"; - $dest_file = "hostnames.txt"; - break; - case "oisd/big \(default\)": - $list_url = "https://big.oisd.nl/dnsmasq"; - $dest_file = "domains.txt"; - break; - case "oisd/small": - $list_url = "https://small.oisd.nl/dnsmasq"; - $dest_file = "domains.txt"; - break; - case "oisd/nsfw": - $list_url = "https://nsfw.oisd.nl/dnsmasq"; - $dest_file = "domains.txt"; - break; + if ($allLists === null) { + echo json_encode([ + 'return' => 3, + 'output' => ['Failed to parse blocklists.json'] + ]); + exit; } - $blocklist = $list_url . $dest_file; - $dest = substr($dest_file, 0, strrpos($dest_file, ".")); + $flatList = flattenList($allLists); + + if (!isset($flatList[$blocklist_id])) { + echo json_encode(['return' => 1, 'output' => ['Invalid blocklist ID']]); + exit; + } + + $list_url = escapeshellcmd($flatList[$blocklist_id]['list_url']); + $dest_file = escapeshellcmd($flatList[$blocklist_id]['dest_file']); + $dest = pathinfo($dest_file, PATHINFO_FILENAME); + $scriptPath = RASPI_CONFIG . '/adblock/update_blocklist.sh'; + + if (!file_exists($scriptPath)) { + echo json_encode([ + 'return' => 5, + 'output' => ["Update script not found: $scriptPath"] + ]); + exit; + } + exec("sudo $scriptPath $list_url $dest_file " . RASPI_ADBLOCK_LISTPATH, $output, $return_var); + echo json_encode([ + 'return' => $return_var, + 'output' => $output, + 'list' => $dest + ]); - exec("sudo /etc/raspap/adblock/update_blocklist.sh $list_url $dest_file " .RASPI_ADBLOCK_LISTPATH, $return); - $jsonData = ['return'=>$return,'list'=>$dest]; - echo json_encode($jsonData); } else { - $jsonData = ['return'=>2,'output'=>['Error getting data']]; - echo json_encode($jsonData); + echo json_encode(['return' => 2, 'output' => ['No blocklist ID provided']]); } + +function flattenList(array $grouped): array { + $flat = []; + foreach ($grouped as $group) { + foreach ($group as $name => $meta) { + $flat[$name] = $meta; + } + } + return $flat; +} + diff --git a/app/js/custom.js b/app/js/custom.js index d95b5405..3e8a7c58 100644 --- a/app/js/custom.js +++ b/app/js/custom.js @@ -730,20 +730,65 @@ function setHardwareModeTooltip() { * Interface elements are updated to indicate current progress, status. */ function updateBlocklist() { - var opt = $('#cbxblocklist option:selected'); - var blocklist_id = opt.val(); - var csrfToken = $('meta[name=csrf_token]').attr('content'); - if (blocklist_id == '') { return; } - $('#cbxblocklist-status').find('i').removeClass('fas fa-check').addClass('fas fa-cog fa-spin'); - $('#cbxblocklist-status').removeClass('check-hidden').addClass('check-progress'); - $.post('ajax/adblock/update_blocklist.php',{ 'blocklist_id':blocklist_id, 'csrf_token': csrfToken},function(data){ - var jsonData = JSON.parse(data); - if (jsonData['return'] == '0') { - $('#cbxblocklist-status').find('i').removeClass('fas fa-cog fa-spin').addClass('fas fa-check'); - $('#cbxblocklist-status').removeClass('check-progress').addClass('check-updated').delay(500).animate({ opacity: 1 }, 700); - $('#blocklist-'+jsonData['list']).text("Just now"); + const opt = $('#cbxblocklist option:selected'); + const blocklist_id = opt.val(); + const csrfToken = $('meta[name=csrf_token]').attr('content'); + + if (blocklist_id === '') return; + + const statusIcon = $('#cbxblocklist-status').find('i'); + const statusWrapper = $('#cbxblocklist-status'); + + statusIcon.removeClass('fa-check fa-exclamation-triangle').addClass('fa-cog fa-spin'); + statusWrapper.removeClass('check-hidden check-error check-updated').addClass('check-progress'); + + $.post('ajax/adblock/update_blocklist.php', { + 'blocklist_id': blocklist_id, + 'csrf_token': csrfToken + }, function (data) { + let jsonData; + try { + jsonData = JSON.parse(data); + } catch (e) { + showError("Unexpected server response."); + return; } - }) + const resultCode = jsonData['return']; + const output = jsonData['output']?.join('\n') || ''; + + switch (resultCode) { + case 0: + statusIcon.removeClass('fa-cog fa-spin').addClass('fa-check'); + statusWrapper.removeClass('check-progress').addClass('check-updated').delay(500).animate({ opacity: 1 }, 700); + $('#blocklist-' + jsonData['list']).text("Just now"); + break; + case 1: + showError("Invalid blocklist."); + break; + case 2: + showError("No blocklist provided."); + break; + case 3: + showError("Could not parse blocklists.json."); + break; + case 4: + showError("blocklists.json file not found."); + break; + case 5: + showError("Update script not found."); + break; + default: + showError("Unknown error occurred."); + } + }).fail(function (jqXHR, textStatus, errorThrown) { + showError(`AJAX request failed: ${textStatus}`); + }); + + function showError(message) { + statusIcon.removeClass('fa-cog fa-spin').addClass('fa-exclamation-triangle'); + statusWrapper.removeClass('check-progress').addClass('check-error'); + alert("Blocklist update failed:\n\n" + message); + } } function clearBlocklistStatus() { diff --git a/config/blocklists.json b/config/blocklists.json index 7138c451..1a3a5e45 100644 --- a/config/blocklists.json +++ b/config/blocklists.json @@ -1,17 +1,45 @@ { - "StevenBlack/hosts": [ - "StevenBlack/hosts (default)" - ], - "badmojr/hosts": [ - "badmojr/1Hosts (Mini)", - "badmojr/1Hosts (Lite)", - "badmojr/1Hosts (Pro)", - "badmojr/1Hosts (Xtra)" - ], - "OISD/domains": [ - "oisd/big (default)", - "oisd/small", - "oisd/nsfw" - ] + "StevenBlack/hosts": { + "StevenBlack/hosts (default)": { + "list_url": "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts", + "dest_file": "hostnames.txt" + } + }, + "HaGeZi/hosts": { + "hagezi/hosts (Light)": { + "list_url": "https://raw.githubusercontent.com/hagezi/dns-blocklists/main/hosts/light.txt", + "dest_file": "hostnames.txt" + }, + "hagezi/hosts (Normal)": { + "list_url": "https://raw.githubusercontent.com/hagezi/dns-blocklists/main/hosts/multi.txt", + "dest_file": "hostnames.txt" + }, + "hagezi/hosts (Pro)": { + "list_url": "https://raw.githubusercontent.com/hagezi/dns-blocklists/main/hosts/pro.txt", + "dest_file": "hostnames.txt" + }, + "hagezi/hosts (Pro++)": { + "list_url": "https://raw.githubusercontent.com/hagezi/dns-blocklists/main/hosts/pro.plus.txt", + "dest_file": "hostnames.txt" + }, + "hagezi/hosts (Ultimate)": { + "list_url": "https://raw.githubusercontent.com/hagezi/dns-blocklists/main/hosts/ultimate.txt", + "dest_file": "hostnames.txt" + } + }, + "OISD/domains": { + "oisd/big (default)": { + "list_url": "https://big.oisd.nl/dnsmasq", + "dest_file": "domains.txt" + }, + "oisd/small": { + "list_url": "https://small.oisd.nl/dnsmasq", + "dest_file": "domains.txt" + }, + "oisd/nsfw": { + "list_url": "https://nsfw.oisd.nl/dnsmasq", + "dest_file": "domains.txt" + } + } } diff --git a/includes/functions.php b/includes/functions.php index f4e26eca..f1b90b9e 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -570,8 +570,13 @@ function dnsServers() function blocklistProviders() { - $data = json_decode(file_get_contents("./config/blocklists.json")); - return (array) $data; + $raw = json_decode(file_get_contents("./config/blocklists.json"), true); + $result = []; + + foreach ($raw as $group => $entries) { + $result[$group] = array_keys($entries); + } + return $result; } function optionsForSelect($options)