mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-08-28 11:37:16 +00:00
Fix security vulnerabilities and logic flaws
This commit is contained in:
+31
-6
@@ -11,11 +11,28 @@ let currentTabId = null;
|
|||||||
let currentTabTitle = null; // New: for Smart Matching
|
let currentTabTitle = null; // New: for Smart Matching
|
||||||
let logs = [];
|
let logs = [];
|
||||||
let history = []; // New: for Action History
|
let history = []; // New: for Action History
|
||||||
|
let storageInitialized = false;
|
||||||
|
let pendingLogs = [];
|
||||||
|
let pendingHistory = [];
|
||||||
|
|
||||||
// Restore state from session storage
|
// Restore state from session storage
|
||||||
chrome.storage.session.get(['logs', 'history'], (data) => {
|
chrome.storage.session.get(['logs', 'history'], (data) => {
|
||||||
if (data.logs) logs = data.logs;
|
if (data.logs) logs = data.logs;
|
||||||
if (data.history) history = data.history;
|
if (data.history) history = data.history;
|
||||||
|
storageInitialized = true;
|
||||||
|
|
||||||
|
if (pendingLogs.length > 0) {
|
||||||
|
logs.unshift(...pendingLogs);
|
||||||
|
if (logs.length > 50) logs = logs.slice(0, 50);
|
||||||
|
chrome.storage.session.set({ logs });
|
||||||
|
pendingLogs = [];
|
||||||
|
}
|
||||||
|
if (pendingHistory.length > 0) {
|
||||||
|
history.unshift(...pendingHistory);
|
||||||
|
if (history.length > 20) history = history.slice(0, 20);
|
||||||
|
chrome.storage.session.set({ history });
|
||||||
|
pendingHistory = [];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let reconnectTimer = null;
|
let reconnectTimer = null;
|
||||||
@@ -56,9 +73,13 @@ function addLog(message, type = 'info') {
|
|||||||
message,
|
message,
|
||||||
type
|
type
|
||||||
};
|
};
|
||||||
logs.unshift(log);
|
if (!storageInitialized) {
|
||||||
if (logs.length > 50) logs.pop();
|
pendingLogs.unshift(log);
|
||||||
chrome.storage.session.set({ logs });
|
} else {
|
||||||
|
logs.unshift(log);
|
||||||
|
if (logs.length > 50) logs.pop();
|
||||||
|
chrome.storage.session.set({ logs });
|
||||||
|
}
|
||||||
chrome.runtime.sendMessage({ type: 'LOG_UPDATE', log }).catch(() => {});
|
chrome.runtime.sendMessage({ type: 'LOG_UPDATE', log }).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,9 +281,13 @@ function addToHistory(action, senderId) {
|
|||||||
senderId: senderId || 'You',
|
senderId: senderId || 'You',
|
||||||
timestamp: new Date().toISOString()
|
timestamp: new Date().toISOString()
|
||||||
};
|
};
|
||||||
history.unshift(historyEntry);
|
if (!storageInitialized) {
|
||||||
if (history.length > 20) history.pop();
|
pendingHistory.unshift(historyEntry);
|
||||||
chrome.storage.session.set({ history });
|
} else {
|
||||||
|
history.unshift(historyEntry);
|
||||||
|
if (history.length > 20) history.pop();
|
||||||
|
chrome.storage.session.set({ history });
|
||||||
|
}
|
||||||
chrome.runtime.sendMessage({ type: 'HISTORY_UPDATE', history }).catch(() => {});
|
chrome.runtime.sendMessage({ type: 'HISTORY_UPDATE', history }).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-15
@@ -7,7 +7,7 @@
|
|||||||
if (window.koalaSyncInjected) return;
|
if (window.koalaSyncInjected) return;
|
||||||
window.koalaSyncInjected = true;
|
window.koalaSyncInjected = true;
|
||||||
|
|
||||||
let isProcessingCommand = false;
|
let processingCommandUntil = 0;
|
||||||
|
|
||||||
// --- Helper: find the best video element on the page ---
|
// --- Helper: find the best video element on the page ---
|
||||||
function findVideo() {
|
function findVideo() {
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
const video = findVideo();
|
const video = findVideo();
|
||||||
if (!video) return;
|
if (!video) return;
|
||||||
|
|
||||||
isProcessingCommand = true;
|
processingCommandUntil = Date.now() + 1000;
|
||||||
try {
|
try {
|
||||||
const host = window.location.hostname.toLowerCase();
|
const host = window.location.hostname.toLowerCase();
|
||||||
const isYouTube = host.includes('youtube.com');
|
const isYouTube = host.includes('youtube.com');
|
||||||
@@ -60,9 +60,6 @@
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('KoalaSync Media Action Error:', e);
|
console.error('KoalaSync Media Action Error:', e);
|
||||||
} finally {
|
|
||||||
// Guarantee reset even on early returns in YouTube/Twitch blocks
|
|
||||||
setTimeout(() => { isProcessingCommand = false; }, 1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,6 +88,12 @@
|
|||||||
|
|
||||||
// Listen for commands from background.js
|
// Listen for commands from background.js
|
||||||
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
if (message.action === 'get_current_time') {
|
||||||
|
const video = findVideo();
|
||||||
|
sendResponse({ currentTime: video ? video.currentTime : undefined });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (message.type === 'SERVER_COMMAND') {
|
if (message.type === 'SERVER_COMMAND') {
|
||||||
const { action, payload } = message;
|
const { action, payload } = message;
|
||||||
|
|
||||||
@@ -101,17 +104,17 @@
|
|||||||
} else if (action === 'seek') {
|
} else if (action === 'seek') {
|
||||||
tryMediaAction('seek', payload);
|
tryMediaAction('seek', payload);
|
||||||
} else if (action === 'force_sync_prepare') {
|
} else if (action === 'force_sync_prepare') {
|
||||||
isProcessingCommand = true;
|
processingCommandUntil = Date.now() + 10000;
|
||||||
const video = findVideo();
|
const video = findVideo();
|
||||||
if (video) {
|
if (video) {
|
||||||
video.pause();
|
video.pause();
|
||||||
video.currentTime = payload.targetTime;
|
video.currentTime = payload.targetTime;
|
||||||
pollSeekReady(payload.targetTime).then(() => {
|
pollSeekReady(payload.targetTime).then(() => {
|
||||||
chrome.runtime.sendMessage({ type: 'FORCE_SYNC_ACK' });
|
chrome.runtime.sendMessage({ type: 'FORCE_SYNC_ACK' });
|
||||||
setTimeout(() => { isProcessingCommand = false; }, 1000);
|
processingCommandUntil = Date.now() + 1000;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
isProcessingCommand = false;
|
processingCommandUntil = 0;
|
||||||
}
|
}
|
||||||
} else if (action === 'force_sync_execute') {
|
} else if (action === 'force_sync_execute') {
|
||||||
tryMediaAction('play');
|
tryMediaAction('play');
|
||||||
@@ -121,7 +124,7 @@
|
|||||||
|
|
||||||
// Detect native events
|
// Detect native events
|
||||||
function reportEvent(action) {
|
function reportEvent(action) {
|
||||||
if (isProcessingCommand) return;
|
if (Date.now() < processingCommandUntil) return;
|
||||||
const video = findVideo();
|
const video = findVideo();
|
||||||
if (!video) return;
|
if (!video) return;
|
||||||
|
|
||||||
@@ -147,15 +150,24 @@
|
|||||||
|
|
||||||
// SPA Navigation Handler (MutationObserver)
|
// SPA Navigation Handler (MutationObserver)
|
||||||
let lastMutate = 0;
|
let lastMutate = 0;
|
||||||
|
let observerTimeout = null;
|
||||||
|
|
||||||
|
function checkVideo() {
|
||||||
|
lastMutate = Date.now();
|
||||||
|
const video = findVideo();
|
||||||
|
if (video && !video.dataset.koalaAttached) {
|
||||||
|
console.log('KoalaSync: New video detected via navigation.');
|
||||||
|
setupListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const observer = new MutationObserver(() => {
|
const observer = new MutationObserver(() => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (now - lastMutate >= 1000) {
|
if (now - lastMutate >= 1000) {
|
||||||
lastMutate = now;
|
checkVideo();
|
||||||
const video = findVideo();
|
} else {
|
||||||
if (video && !video.dataset.koalaAttached) {
|
if (observerTimeout) clearTimeout(observerTimeout);
|
||||||
console.log('KoalaSync: New video detected via navigation.');
|
observerTimeout = setTimeout(checkVideo, 1000 - (now - lastMutate));
|
||||||
setupListeners();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
observer.observe(document.body, { childList: true, subtree: true });
|
observer.observe(document.body, { childList: true, subtree: true });
|
||||||
|
|||||||
+9
-6
@@ -337,12 +337,15 @@ function showError(msg) {
|
|||||||
elements.password.style.borderColor = 'var(--error)';
|
elements.password.style.borderColor = 'var(--error)';
|
||||||
|
|
||||||
// Shake effect
|
// Shake effect
|
||||||
document.getElementById('tab-room').animate([
|
const activeTab = document.querySelector('.tab-content.active');
|
||||||
{ transform: 'translateX(0)' },
|
if (activeTab) {
|
||||||
{ transform: 'translateX(-5px)' },
|
activeTab.animate([
|
||||||
{ transform: 'translateX(5px)' },
|
{ transform: 'translateX(0)' },
|
||||||
{ transform: 'translateX(0)' }
|
{ transform: 'translateX(-5px)' },
|
||||||
], { duration: 200, iterations: 2 });
|
{ transform: 'translateX(5px)' },
|
||||||
|
{ transform: 'translateX(0)' }
|
||||||
|
], { duration: 200, iterations: 2 });
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (elements.roomError) elements.roomError.style.display = 'none';
|
if (elements.roomError) elements.roomError.style.display = 'none';
|
||||||
|
|||||||
@@ -84,6 +84,16 @@ setInterval(() => {
|
|||||||
|
|
||||||
const eventCounts = new Map(); // socketId -> { count, resetTime }
|
const eventCounts = new Map(); // socketId -> { count, resetTime }
|
||||||
|
|
||||||
|
// Clean up connection counts to prevent memory leak
|
||||||
|
setInterval(() => {
|
||||||
|
const now = Date.now();
|
||||||
|
for (const [ip, entry] of connectionCounts.entries()) {
|
||||||
|
if (now > entry.resetTime) {
|
||||||
|
connectionCounts.delete(ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 60000);
|
||||||
|
|
||||||
function checkConnectionRate(ip) {
|
function checkConnectionRate(ip) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const entry = connectionCounts.get(ip) || { count: 0, resetTime: now + 60000 };
|
const entry = connectionCounts.get(ip) || { count: 0, resetTime: now + 60000 };
|
||||||
@@ -150,6 +160,9 @@ io.on('connection', (socket) => {
|
|||||||
|
|
||||||
// Cleanup old room if re-joining
|
// Cleanup old room if re-joining
|
||||||
const oldMapping = socketToRoom.get(socket.id);
|
const oldMapping = socketToRoom.get(socket.id);
|
||||||
|
if (oldMapping && oldMapping.roomId === roomId) {
|
||||||
|
return; // Already in this room, ignore to prevent spam
|
||||||
|
}
|
||||||
if (oldMapping && oldMapping.roomId !== roomId) {
|
if (oldMapping && oldMapping.roomId !== roomId) {
|
||||||
socket.leave(oldMapping.roomId);
|
socket.leave(oldMapping.roomId);
|
||||||
const oldRoom = rooms.get(oldMapping.roomId);
|
const oldRoom = rooms.get(oldMapping.roomId);
|
||||||
@@ -232,6 +245,8 @@ io.on('connection', (socket) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!data || typeof data !== 'object') return; // Prevent null/invalid payload crash
|
||||||
|
|
||||||
const mapping = socketToRoom.get(socket.id);
|
const mapping = socketToRoom.get(socket.id);
|
||||||
if (mapping) {
|
if (mapping) {
|
||||||
const room = rooms.get(mapping.roomId);
|
const room = rooms.get(mapping.roomId);
|
||||||
|
|||||||
Reference in New Issue
Block a user