275 lines
9.2 KiB
PHP
275 lines
9.2 KiB
PHP
<p id="warning" style="color:red; display:none;">Cannot confirm: the symbol 𒐫 is still present in the JSON to append.</p>
|
|
<script>
|
|
function checkForSymbol() {
|
|
const toAppendElems = document.querySelectorAll('.to-append');
|
|
let found = false;
|
|
toAppendElems.forEach(el => {
|
|
if (el.textContent.includes('𒐫')) found = true;
|
|
});
|
|
const confirmBtn = document.getElementById('confirm-btn');
|
|
const warning = document.getElementById('warning');
|
|
if (found) {
|
|
confirmBtn.disabled = true;
|
|
warning.style.display = 'block';
|
|
} else {
|
|
confirmBtn.disabled = false;
|
|
warning.style.display = 'none';
|
|
}
|
|
}
|
|
document.addEventListener('DOMContentLoaded', checkForSymbol);
|
|
</script>
|
|
<?php
|
|
session_set_cookie_params(['secure' => true, 'httponly' => true, 'samesite' => 'Strict']);
|
|
session_start();
|
|
$session_lifetime = 3 * 60;
|
|
$correct_username = "admin";
|
|
$correct_password_hash = '$2y$10$S9naYnE6MqP14zVRfIsig.A98jBGzEImaGLgKVuiSGKpI7yr7XeGG'; // password: 4869
|
|
|
|
if (isset($_GET['logout'])) {
|
|
session_unset();
|
|
session_destroy();
|
|
header("Location: " . $_SERVER['PHP_SELF']);
|
|
exit;
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['heartbeat'])) {
|
|
$_SESSION['last_activity'] = time();
|
|
exit;
|
|
}
|
|
|
|
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$username = $_POST['username'] ?? '';
|
|
$password = $_POST['password'] ?? '';
|
|
if ($username === $correct_username && password_verify($password, $correct_password_hash)) {
|
|
session_regenerate_id(true);
|
|
$_SESSION['logged_in'] = true;
|
|
$_SESSION['last_activity'] = time();
|
|
header("Location: " . $_SERVER['PHP_SELF']);
|
|
exit;
|
|
} else {
|
|
$error = "Invalid username or password.";
|
|
}
|
|
}
|
|
?>
|
|
<?php if (isset($error)) echo "<p style='color:red;'>$error</p>"; ?>
|
|
<form method="post">
|
|
<label>Username: <input name="username" required></label><br>
|
|
<label>Password: <input type="password" name="password" required></label><br>
|
|
<button type="submit">Login</button>
|
|
</form>
|
|
<?php
|
|
exit;
|
|
}
|
|
|
|
if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity']) > $session_lifetime) {
|
|
session_unset();
|
|
session_destroy();
|
|
header("Location: " . $_SERVER['PHP_SELF']);
|
|
exit;
|
|
}
|
|
|
|
$_SESSION['last_activity'] = time();
|
|
$remaining_time = ($_SESSION['last_activity'] + $session_lifetime) - time();
|
|
?>
|
|
|
|
Welcome, you are logged in! <span id="countdown"></span><hr>
|
|
<a href="?logout=1">Logout</a>
|
|
<script>
|
|
let remaining = <?php echo $remaining_time; ?>;
|
|
function updateCountdown() {
|
|
if (remaining <= 0) {
|
|
clearInterval(timer);
|
|
alert("Session expired due to inactivity.");
|
|
location.reload();
|
|
return;
|
|
}
|
|
const minutes = Math.floor(remaining / 60);
|
|
const seconds = remaining % 60;
|
|
document.getElementById('countdown').textContent =
|
|
minutes + "m " + (seconds < 10 ? "0" : "") + seconds + "s";
|
|
remaining--;
|
|
}
|
|
updateCountdown();
|
|
const timer = setInterval(updateCountdown, 1000);
|
|
setInterval(() => {
|
|
fetch("", {
|
|
method: "POST",
|
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
body: "heartbeat=1"
|
|
});
|
|
}, 30000);
|
|
</script>
|
|
|
|
|
|
|
|
<?php
|
|
$remoteUrl = 'https://alceawis.de/other/extra/scripts/fakesocialmedia/data_part_alcea.json';
|
|
$localFile = 'data_alcea.json';
|
|
|
|
function convertToBlockquoteTags(string $text): string {
|
|
return preg_replace('/𒐫(.*?)𒐫/us', '<blockquote>$1</blockquote>', $text);
|
|
}
|
|
|
|
function convertToUnicodeEnclosure(string $text): string {
|
|
return preg_replace('/<blockquote>(.*?)<\/blockquote>/us', '𒐫$1𒐫', $text);
|
|
}
|
|
|
|
function array_map_recursive(callable $callback, $array) {
|
|
foreach ($array as $key => $value) {
|
|
if (is_array($value)) {
|
|
$array[$key] = array_map_recursive($callback, $value);
|
|
} else {
|
|
$array[$key] = $callback($value);
|
|
}
|
|
}
|
|
return $array;
|
|
}
|
|
|
|
function convertDataToCompareFormat(array $data): array {
|
|
return array_map_recursive(function ($v) {
|
|
return is_string($v) ? convertToUnicodeEnclosure($v) : $v;
|
|
}, $data);
|
|
}
|
|
|
|
// ✅ NEW: Strip all non-message keys (keep only 'value')
|
|
function stripNonMessageKeys($array) {
|
|
$result = [];
|
|
foreach ($array as $dateKey => $payload) {
|
|
if (is_array($payload) && isset($payload['value'])) {
|
|
$result[$dateKey] = ['value' => $payload['value']];
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
function entryExists(array $entry, array $local): bool {
|
|
$needle = stripNonMessageKeys($entry);
|
|
$needleJson = json_encode($needle, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
|
|
foreach ($local as $item) {
|
|
$haystack = stripNonMessageKeys($item);
|
|
$haystackJson = json_encode($haystack, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
if ($needleJson === $haystackJson) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Load remote
|
|
$remoteJson = file_get_contents($remoteUrl);
|
|
if (!$remoteJson) die(" Failed to load remote JSON.");
|
|
$remoteRaw = json_decode($remoteJson, true);
|
|
if (!is_array($remoteRaw)) die(" Failed to decode remote JSON.");
|
|
|
|
// Load local
|
|
if (!file_exists($localFile)) die(" Local JSON file '$localFile' not found.");
|
|
$localJson = file_get_contents($localFile);
|
|
$localRaw = json_decode($localJson, true);
|
|
if (!is_array($localRaw)) die(" Failed to decode local JSON.");
|
|
|
|
// Normalize local for comparison
|
|
$localForCompare = array_map('convertDataToCompareFormat', $localRaw);
|
|
|
|
// Find new entries
|
|
$newRemoteEntries = [];
|
|
$current_time = date('YmdHis'); // Current timestamp in the format YmdHis
|
|
|
|
foreach ($remoteRaw as $entry) {
|
|
foreach ($entry as $payload) {
|
|
if (isset($payload['value']) && strpos($payload['value'], '•acws') !== false) {
|
|
$original = $entry;
|
|
$converted = array_map_recursive(function ($v) {
|
|
return is_string($v) ? convertToBlockquoteTags($v) : $v;
|
|
}, $entry);
|
|
if (!entryExists(convertDataToCompareFormat($converted), $localForCompare)) {
|
|
$newRemoteEntries[] = [
|
|
'original' => $original,
|
|
'to_append' => $converted,
|
|
'time' => $current_time // Add the 'time' key with the timestamp
|
|
];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Confirm save
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm'])) {
|
|
if (count($newRemoteEntries) > 0) {
|
|
$newConverted = array_map(function ($e) {
|
|
$converted = $e['to_append'];
|
|
foreach ($converted as $dateKey => &$payload) {
|
|
if (is_array($payload) && isset($payload['value'])) {
|
|
$payload['time'] = $e['time'];
|
|
$hash = substr(md5($payload['value']), 0, 8);
|
|
$payload['status'] = "{$dateKey}-$hash";
|
|
}
|
|
}
|
|
return $converted;
|
|
}, $newRemoteEntries);
|
|
|
|
$newData = array_merge($newConverted, $localRaw);
|
|
|
|
$written = file_put_contents(
|
|
$localFile,
|
|
json_encode($newData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
|
);
|
|
|
|
if ($written === false) {
|
|
echo "<p style='color:red;'>Failed to write to local file.</p>";
|
|
} else {
|
|
echo "<p style='color:green;'>Added " . count($newConverted) . " new entries to <code>$localFile</code>.</p>";
|
|
$newRemoteEntries = [];
|
|
}
|
|
}
|
|
}
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Review New •acws Entries</title>
|
|
<style>
|
|
body { font-family: sans-serif; max-width: 1000px; margin: 2em auto; }
|
|
pre { background: #f5f5f5; padding: 1em; border-radius: 5px; white-space: pre-wrap; }
|
|
.entry-pair { display: flex; gap: 20px; margin-bottom: 2em; }
|
|
.entry-pair > div { width: 50%; }
|
|
button { padding: 0.6em 1em; font-size: 1em; cursor: pointer; }
|
|
h2 { margin-top: 3em; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>New <code>•acws</code> Entries</h1>
|
|
<?php if (count($newRemoteEntries) > 0): ?>
|
|
<p><strong><?php echo count($newRemoteEntries); ?></strong> new entries found in remote file not present in local.</p>
|
|
<?php foreach ($newRemoteEntries as $index => $entryPair): ?>
|
|
<div class="entry-pair">
|
|
<div>
|
|
<h2>Original Message #<?php echo $index + 1; ?></h2>
|
|
<pre><?php echo htmlspecialchars(json_encode($entryPair['original'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); ?></pre>
|
|
</div>
|
|
<div>
|
|
<h2>JSON to be Appended</h2>
|
|
<pre>
|
|
<?php
|
|
$to_append_with_time = $entryPair['to_append'];
|
|
$to_append_with_time['time'] = $entryPair['time'];
|
|
echo htmlspecialchars(json_encode($to_append_with_time, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
?>
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
|
|
<form method="post">
|
|
<button id="confirm-btn" name="confirm" type="submit">Confirm Append</button>
|
|
</form>
|
|
<?php else: ?>
|
|
<p>No new <code>•acws</code> entries found.</p>
|
|
<?php endif; ?>
|
|
|
|
</body>
|
|
</html>
|