// ==UserScript==
// @name Stop Nefarious Redirects
// @namespace http://tampermonkey.net/
// @version 3.89
// @description Block unauthorized redirects and prevent history manipulation
// @match http://*/*
// @match https://*/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @license MIT
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// Manual blacklist
const manualBlacklist = new Set([
'getrunkhomuto.info'
]);
// Function to get the current automated blacklist
function getAutomatedBlacklist() {
return new Set(GM_getValue('blacklist', []));
}
// Function to add a URL to the automated blacklist
function addToAutomatedBlacklist(url) {
let encodedUrl = encodeURIComponent(url);
let blacklist = getAutomatedBlacklist();
if (!blacklist.has(encodedUrl)) {
blacklist.add(encodedUrl);
GM_setValue('blacklist', Array.from(blacklist));
console.log('Added to automated blacklist:', url);
}
}
// Function to display the blacklist
function displayBlacklist() {
let automatedBlacklist = getAutomatedBlacklist();
let fullBlacklist = new Set([...manualBlacklist, ...automatedBlacklist]);
console.log('Current Blacklist:\n' + Array.from(fullBlacklist).map(decodeURIComponent).join('\n'));
alert('Current Blacklist:\n' + Array.from(fullBlacklist).map(decodeURIComponent).join('\n'));
}
// Function to handle navigation events
function handleNavigation(url) {
try {
if (!isUrlAllowed(url)) {
console.error('Blocked navigation to:', url);
addToAutomatedBlacklist(url); // Add the unauthorized URL to the automated blacklist
if (lastKnownGoodUrl) {
window.location.replace(lastKnownGoodUrl);
}
return false;
} else {
console.log('Navigation allowed to:', url);
lastKnownGoodUrl = url;
return true;
}
} catch (error) {
console.error('Error in handleNavigation:', error);
}
}
let lastKnownGoodUrl = window.location.href;
let navigationInProgress = false;
// Proxy to intercept and handle location changes
const locationProxy = new Proxy(window.location, {
set(target, prop, value) {
if ((prop === 'href' || prop === 'assign' || prop === 'replace') && !navigationInProgress) {
if (!handleNavigation(value)) {
return false;
}
}
return Reflect.set(target, prop, value);
},
get(target, prop) {
if (prop === 'assign' || prop === 'replace') {
return function(url) {
if (!navigationInProgress && handleNavigation(url)) {
navigationInProgress = true;
setTimeout(() => {
navigationInProgress = false;
}, 0);
return target[prop].call(target, url);
}
};
}
return Reflect.get(target, prop);
}
});
// Replace window.location with the proxy
Object.defineProperty(window, 'location', {
configurable: true,
enumerable: true,
get() {
return locationProxy;
}
});
// Monitor window.open() calls
const originalOpen = window.open;
window.open = function(url) {
if (handleNavigation(url)) {
return originalOpen.apply(this, arguments);
}
};
// Monitor document.createElement('a') calls
const originalCreateElement = document.createElement;
document.createElement = function(tagName) {
const element = originalCreateElement.call(document, tagName);
if (tagName.toLowerCase() === 'a') {
const originalSetAttribute = element.setAttribute;
element.setAttribute = function(name, value) {
if (name === 'href') {
if (!handleNavigation(value)) {
return;
}
}
return originalSetAttribute.apply(this, arguments);
};
}
return element;
};
// Enhanced navigation control for back/forward buttons
window.addEventListener('popstate', function(event) {
if (!navigationInProgress && !isUrlAllowed(window.location.href)) {
console.error('Blocked navigation to:', window.location.href);
navigationInProgress = true;
setTimeout(() => {
navigationInProgress = false;
}, 0);
history.pushState(null, "", lastKnownGoodUrl); // Push the last known good URL
window.location.replace(lastKnownGoodUrl); // Force redirect to last known good URL
event.preventDefault();
}
});
// Function to handle history manipulation
function handleHistoryManipulation(originalMethod, data, title, url) {
if (!isUrlAllowed(url)) {
console.error('Blocked history manipulation to:', url);
return;
}
return originalMethod.call(history, data, title, url);
}
// Wrap history.pushState and history.replaceState
const originalPushState = history.pushState;
const originalReplaceState = history.replaceState;
history.pushState = function(data, title, url) {
return handleHistoryManipulation(originalPushState, data, title, url);
};
history.replaceState = function(data, title, url) {
return handleHistoryManipulation(originalReplaceState, data, title, url);
};
// Ensure we have a state to go back to if needed
if (history.length === 1) {
// Directly landed on this page, fake history
history.replaceState(null, "", "/");
history.pushState(null, "", window.location.href);
}
// Function to check if a URL is allowed based on the blacklist
function isUrlAllowed(url) {
let encodedUrl = encodeURIComponent(url);
let automatedBlacklist = getAutomatedBlacklist();
let isBlocked = Array.from(manualBlacklist).some(blockedUrl => encodedUrl.includes(blockedUrl)) ||
Array.from(automatedBlacklist).some(blockedUrl => encodedUrl.includes(blockedUrl));
if (isBlocked) {
console.log(`Blocked URL: ${url}`);
}
return !isBlocked;
}
console.log('Redirect control script with blacklist initialized.');
})();