feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory - Added PROJECT_OVERVIEW.md with feature highlights and getting started guide - Added ARCHITECTURE.md with system design and technical details - Added SECURITY.md with comprehensive security implementation guide - Added DEVELOPMENT.md with development workflows and best practices - Added DEPLOYMENT.md with production deployment instructions - Added API.md with complete REST API documentation - Added CONTRIBUTING.md with contribution guidelines - Added CHANGELOG.md with version history and migration notes - Reorganized all documentation files into docs/ directory for better organization - Updated README.md with proper documentation links and quick navigation - Enhanced project structure with professional documentation standards
This commit is contained in:
147
f_templates/fingerprint_template.tpl
Normal file
147
f_templates/fingerprint_template.tpl
Normal file
@@ -0,0 +1,147 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{$page_title|default:"EasyStream"}</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- Your existing head content -->
|
||||
</head>
|
||||
<body>
|
||||
<!-- Your existing body content -->
|
||||
|
||||
<!-- Browser Fingerprinting Script -->
|
||||
{literal}
|
||||
<script>
|
||||
function generateFingerprint() {
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.textBaseline = "top";
|
||||
ctx.font = "14px Arial";
|
||||
ctx.fillText("Browser fingerprint", 2, 2);
|
||||
|
||||
const fingerprint = {
|
||||
screen_resolution: screen.width + "x" + screen.height,
|
||||
screen_color_depth: screen.colorDepth,
|
||||
timezone_offset: new Date().getTimezoneOffset(),
|
||||
language: navigator.language,
|
||||
languages: navigator.languages ? navigator.languages.join(",") : "",
|
||||
platform: navigator.platform,
|
||||
cookie_enabled: navigator.cookieEnabled,
|
||||
do_not_track: navigator.doNotTrack,
|
||||
canvas_fingerprint: canvas.toDataURL(),
|
||||
webgl_vendor: getWebGLVendor(),
|
||||
webgl_renderer: getWebGLRenderer(),
|
||||
plugins: getPluginsList(),
|
||||
fonts: detectFonts(),
|
||||
hardware_concurrency: navigator.hardwareConcurrency,
|
||||
device_memory: navigator.deviceMemory,
|
||||
connection_type: navigator.connection ? navigator.connection.effectiveType : "",
|
||||
touch_support: "ontouchstart" in window,
|
||||
local_storage: typeof(Storage) !== "undefined",
|
||||
session_storage: typeof(sessionStorage) !== "undefined",
|
||||
indexed_db: typeof(indexedDB) !== "undefined"
|
||||
};
|
||||
|
||||
return fingerprint;
|
||||
}
|
||||
|
||||
function getWebGLVendor() {
|
||||
try {
|
||||
const canvas = document.createElement("canvas");
|
||||
const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
|
||||
if (gl) {
|
||||
const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
|
||||
return debugInfo ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) : "";
|
||||
}
|
||||
} catch (e) {}
|
||||
return "";
|
||||
}
|
||||
|
||||
function getWebGLRenderer() {
|
||||
try {
|
||||
const canvas = document.createElement("canvas");
|
||||
const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
|
||||
if (gl) {
|
||||
const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
|
||||
return debugInfo ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : "";
|
||||
}
|
||||
} catch (e) {}
|
||||
return "";
|
||||
}
|
||||
|
||||
function getPluginsList() {
|
||||
const plugins = [];
|
||||
for (let i = 0; i < navigator.plugins.length; i++) {
|
||||
plugins.push(navigator.plugins[i].name);
|
||||
}
|
||||
return plugins.join(",");
|
||||
}
|
||||
|
||||
function detectFonts() {
|
||||
const testFonts = ["Arial", "Helvetica", "Times", "Courier", "Verdana", "Georgia", "Palatino", "Garamond"];
|
||||
const detectedFonts = [];
|
||||
|
||||
const testString = "mmmmmmmmmmlli";
|
||||
const testSize = "72px";
|
||||
const h = document.getElementsByTagName("body")[0];
|
||||
|
||||
const baseFonts = ["monospace", "sans-serif", "serif"];
|
||||
const testDiv = document.createElement("div");
|
||||
testDiv.style.position = "absolute";
|
||||
testDiv.style.left = "-9999px";
|
||||
testDiv.style.fontSize = testSize;
|
||||
testDiv.innerHTML = testString;
|
||||
|
||||
const defaultWidths = {};
|
||||
for (let i = 0; i < baseFonts.length; i++) {
|
||||
testDiv.style.fontFamily = baseFonts[i];
|
||||
h.appendChild(testDiv);
|
||||
defaultWidths[baseFonts[i]] = testDiv.offsetWidth;
|
||||
h.removeChild(testDiv);
|
||||
}
|
||||
|
||||
for (let i = 0; i < testFonts.length; i++) {
|
||||
let detected = false;
|
||||
for (let j = 0; j < baseFonts.length; j++) {
|
||||
testDiv.style.fontFamily = testFonts[i] + "," + baseFonts[j];
|
||||
h.appendChild(testDiv);
|
||||
const matched = (testDiv.offsetWidth !== defaultWidths[baseFonts[j]]);
|
||||
h.removeChild(testDiv);
|
||||
detected = detected || matched;
|
||||
}
|
||||
if (detected) {
|
||||
detectedFonts.push(testFonts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return detectedFonts.join(",");
|
||||
}
|
||||
|
||||
// Send fingerprint to server
|
||||
function sendFingerprint() {
|
||||
const fingerprint = generateFingerprint();
|
||||
|
||||
fetch("/fingerprint_handler.php", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(fingerprint)
|
||||
}).then(response => {
|
||||
if (response.status === 403) {
|
||||
// Fingerprint is banned
|
||||
window.location.href = '/error';
|
||||
}
|
||||
}).catch(console.error);
|
||||
}
|
||||
|
||||
// Auto-send fingerprint when page loads
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", sendFingerprint);
|
||||
} else {
|
||||
sendFingerprint();
|
||||
}
|
||||
</script>
|
||||
{/literal}
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user