From: David Polakovic Date: Tue, 15 Apr 2025 14:58:09 +0000 (+0200) Subject: added dead drop and footer update X-Git-Url: https://git.dpolakovic.space/?a=commitdiff_plain;h=e9ec345105b69b7fb731cfdb7ad2e50b64bb80d7;p=my-website added dead drop and footer update --- diff --git a/blog.php b/blog.php index a84003e..2fc0789 100755 --- a/blog.php +++ b/blog.php @@ -24,11 +24,11 @@ @@ -60,7 +60,7 @@ Publications on this domain are licensed under CC BY-SA 4.0.
- This site is javascript and cookie free. The source code is available + This site uses no client side scripting. The source code is available here under GPLv3 license. diff --git a/dead-drop.php b/dead-drop.php new file mode 100755 index 0000000..bd51e79 --- /dev/null +++ b/dead-drop.php @@ -0,0 +1,84 @@ + + + + + + dpolakovic.space + + + + + + + + + + + + + + + + + + + +
+

+

Dead drop

+ Tradecraft meets bored hackers. +
+
+ A dead drop is a spy technique used for anonymous information exchange. When you stash your + message in a dead drop, it will be hidden from anyone who doesn't know its location. It + also uses MD5 hashing and AES-256-CBC encryption to keep it hidden from the hosting provider + and webmaster as well. Enter the coordinates of a dead drop to check if it's hot (has stashed message) + or if it's cold (empty). + +


+

+

+

+ +
+

+

+
+

+ + + Every dead drop goes cold after 18 hours. +

+
+

+
+ + + +

+ + + diff --git a/dir.php b/dir.php deleted file mode 100755 index bfb194f..0000000 --- a/dir.php +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - dpolakovic.space - - - - - - - - - - - - - - - - - -
-

-

My Web directory

- Let's explore the Web. -
-
- The online space is vast and still expanding. Sadly, not thanks to - the users but rather spam bots and focus black holes - the social networks. - Therefore it's good practice for surfers to share links between each other - in "web directories" like this one. So here are links I thought you might - find useful. -

-

- software
- Free software directory - - a collaborative catalog of free software
- WinWorld - - online museum/library of vintage operating systems
- Infocom catalog - - every Infocom text adventure ever
- KolibriOS - - operating system on 1,44MB floppy
- AtariAge - - hub for enthusiasts of Atari PCs and consoles
-

-

- programming
- Which JDK? - - neat website for navigating alternative Java Dev Kits
- SDKman - - must have tool for every JVM based project
- MVN repository - - Java libraries packed in .jars
- Perl monks - - best place to seek help and wisdom in Perl
- Rosetta Code - - solutions for many tasks in many languages [2]
- Git cheat sheet - - feel free to laugh, but I use this a lot [PDF] -

-

- tools & tutorials
- Cidr.xyz - - when you don't want to die over subnet tables [3]
- Broken link checker - - it does, exactly what it says [3]
- Installing Wine on Linux - - this is tricky task for many distros
-

-

- other
- Linux Kernel Mailing List - - this is my preferred instance
- Lack rack - - nice hack that I use for my servers
- Floppydisk.com - - new and refurbished floppies for okay prices [3]
- Webring list - - pick a community and meet fellow netizens
- Project Gutenberg - - my go to place to get books online
- Av8ns thermodynamics - - thermodynamics reference page
- SWPC NOAA - - space weather forecast [3]
- UESP wiki - - everything I ever needed for Morrowind [1, 3] -

-
-
-

- Some of these websites contains "allergens"
- [1] - advertisements, - [2] - unnecessary cookies, - [3] - proprietary javascript -

-
-
- - - -

- - - diff --git a/index.php b/index.php index 308807a..4377420 100755 --- a/index.php +++ b/index.php @@ -28,12 +28,12 @@ @@ -70,6 +70,8 @@ (how to use GPG keys?)

+

+


@@ -92,7 +94,7 @@ Publications on this domain are licensed under CC BY-SA 4.0.
- This site is javascript and cookie free. The source code is available + This site uses no client side scripting. The source code is available here under GPLv3 license. diff --git a/mars-clock.php b/mars-clock.php index 7f1d7c1..f79f60a 100755 --- a/mars-clock.php +++ b/mars-clock.php @@ -26,12 +26,12 @@

@@ -83,9 +83,16 @@ Conv. Prime Meridian | | | converted time with actual daylight on the Red Planet.

- As you can see, the Mars clock is not autoupdating itself like traditional clock, + Note, that original Darian calendar designates the first + day of each month as the start of a new week, which results in a one-day weekend occurring + three or four times a year. I am uncertain how this would be received by future Martian + colonists, so I didn't implemented this feature as well as + winter/summer time shifts or any holidays whatsoever. +

+

+ Also, the clocks are not updating automatically like clocks usually do, because I didn't want to DDOS myself nor invade your client with - any scripting. It is also not very usefull extraterrestrially, + any scripting. It is also not very useful extraterrestrially, so I made a portable version which you can fit on your Raspberry Pi or any device running Java. It runs in GUI mode and terminal as well.

@@ -115,7 +122,7 @@ Conv. Prime Meridian | | | Publications on this domain are licensed under CC BY-SA 4.0.
- This site is javascript and cookie free. The source code is available + This site uses no client side scripting. The source code is available here under GPLv3 license. diff --git a/php/config.php b/php/config.php index bb9efcc..3bd7f2e 100755 --- a/php/config.php +++ b/php/config.php @@ -1,35 +1,35 @@ = 200 && $httpCode < 300); -} + $domain = parse_url($url, PHP_URL_HOST); + $port = 80; + + // Use port 443 if the URL scheme is HTTPS + if (parse_url($url, PHP_URL_SCHEME) == 'https') { + $port = 443; + } + // Try to open a socket connection to the domain on the specified port + $connection = @fsockopen($domain, $port, $errno, $errstr, 2); + + if ($connection) { + fclose($connection); + return true; + } else { + return false; + } +} // Function displays
  • element on navigation bar // either online or offline status of gitserver function serverStatus() { - $websiteUrl = "https://git.dpolakovic.space"; - - if (isWebsiteOnline($websiteUrl)) { - echo ''. - 'Git server | online'; - } - else { - echo 'Git server | offline'; - } + $websiteUrl = "https://git.dpolakovic.space"; + + if (isWebsiteOnline($websiteUrl)) { + echo 'Git server | online'; + } else { + echo 'Git server | offline'; + } } // Function for index.php to generate random second sentence @@ -61,7 +61,6 @@ function printYear() { else { echo "2023"; } } - // Function to convert RSS file into blog page function printBlog2($rss_file) { @@ -98,7 +97,6 @@ function printBlog2($rss_file) { } } - // Function to print my books on the website function printLibraryTable() { // Read the contents of the lib.txt file @@ -140,4 +138,68 @@ function printLibraryTable() { } +function keyGen() { + // Define the alphabet + $alphabet = 'abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVXYZ013456789?!-()'; + + // Generate the 50 character string + $key = ''; + $length = 50; + + // Ensuring exactly one 'W', exactly one '.' or exactly two ',', exactly one 'x0' (next to each other), and exactly two '2's + $key .= 'W'; // Add 'W' at a random position later + $key .= '2'; // Add one '2' at a random position later + $key .= '2'; // Add second '2' at a random position later + + // Decide randomly between adding a single '.' or two commas (',') + if (rand(0, 1)) { + $key .= '.'; // Add a single dot + } else { + $key .= ',,'; // Add two commas + } + + // Fill the rest of the string with random characters from the alphabet + $remainingLength = $length - strlen($key); + for ($i = 0; $i < $remainingLength; $i++) { + $key .= $alphabet[rand(0, strlen($alphabet) - 1)]; + } + + // Randomly shuffle the characters to place everything in random positions + $key = str_shuffle($key); + + // Generate the current date and time in format YYYYMMDDHHMM + $currentDate = date("YmdHis"); + $currentDate = substr($currentDate, 0, 12); // Extract just the YYYYMMDDHHMM part + + // Convert the date to letters (1 -> a, 2 -> b, 3 -> c, etc.) + $dateInLetters = ''; + for ($i = 0; $i < strlen($currentDate); $i++) { + $digit = (int)$currentDate[$i]; + $dateInLetters .= chr(97 + $digit); // 97 is ASCII for 'a' + } + + // Concatenate the 50-character key and the converted date + $result = $key . $dateInLetters; + + return $result; +} + +function generateNewKey() { + // Path to the file + $file = 'strawberry'; + + // Read the content of the file + $fileContents = file($file, FILE_IGNORE_NEW_LINES); + + // Get the generated key from the keyGen function + $newKey = keyGen(); + + // Substitute the fifth line with the new key + $fileContents[4] = $newKey; + + // Write the updated content back to the file + file_put_contents($file, implode(PHP_EOL, $fileContents) . PHP_EOL); + +} + ?> \ No newline at end of file diff --git a/php/dd.php b/php/dd.php new file mode 100644 index 0000000..eaade51 --- /dev/null +++ b/php/dd.php @@ -0,0 +1,275 @@ + 1){ + echo "There are $fileCount hot drops on this domain right now."; + } + + } else { + echo "Directory '$directory' does not exist."; + } + +} + +function cleanTheCity() { + $directory = "./Dead-drops"; + $now = time(); + $expiry = 18 * 3600; + + if (is_dir($directory)) { + $files = scandir($directory); + foreach ($files as $file) { + // Skip the specific file by name + if ($file == '75cfce5a009d44910a23bd55a3f8f0bd') { + continue; + } + + $filePath = $directory . DIRECTORY_SEPARATOR . $file; + if (is_file($filePath)) { + $fileAge = $now - filemtime($filePath); + if ($fileAge > $expiry) { + unlink($filePath); + } + } + } + } else { + echo "

    Error: Folder ./Locations not found.

    "; + } +} + + + +function deadDropUI() { + session_start(); + $csrf_lifetime = 600; + $session_id_key = 'csrf_token_session_id'; + + if (!isset($_SESSION['csrf_token'], $_SESSION['csrf_token_time'], $_SESSION[$session_id_key]) || + session_id() !== $_SESSION[$session_id_key] || + time() - $_SESSION['csrf_token_time'] > $csrf_lifetime) { + $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); + $_SESSION['csrf_token_time'] = time(); + $_SESSION[$session_id_key] = session_id(); + } + + $token = $_SESSION['csrf_token']; + $result = deadDropLogic(); + $dropCount = count(glob('./Dead-drops/*')); + + if (($result['mode'] === 'initial' && $dropCount < 501) || + ($result['mode'] === 'readonly' && $result['status'] === 'invalid')) { + echo <<input[type="text"],input[type="submit"] { font-size: 16.5px; } +
    + + + + +
    + HTML; + } elseif ($result['mode'] === 'initial' && $dropCount >= 501) { + echo "This domain is too hot. Come back later when there won't be so much heat"; + } + + if ($result['mode'] === 'readonly') { + if ($result['status'] === 'hot') { + echo "
    " . htmlspecialchars($result['decrypted'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . "
    "; + echo << + + + + + HTML; + } elseif ($result['status'] === 'cold') { + echo "

    " . htmlentities($result['w3w']) ."

    This drop is cold. You can stash your message here.

    "; + echo << + + +

    + + + HTML; + } elseif ($result['status'] === 'invalid') { + echo "
    {$result['message']}"; + } + } elseif ($result['mode'] === 'stashed') { + echo "

    Message stashed at " . htmlentities($result['w3w']) ."

    Your dead drop is hot."; + } +} + +function deadDropLogic() { + session_start(); + $csrf_lifetime = 600; + $session_id_key = 'csrf_token_session_id'; + + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + if (!isset($_POST['csrf_token'], $_SESSION['csrf_token'], $_SESSION['csrf_token_time'], $_SESSION[$session_id_key]) || + $_POST['csrf_token'] !== $_SESSION['csrf_token'] || + session_id() !== $_SESSION[$session_id_key] || + time() - $_SESSION['csrf_token_time'] > $csrf_lifetime) { + die('CSRF token invalid or expired. Reload the website, that usually helps...'); + } + + if (isset($_POST['burnW3W'])) { + $input = trim($_POST['burnW3W']); + $hashed = md5($input); + if (!isValidHash($hashed)) die('Invalid hash'); + $file = './Dead-drops/' . $hashed; + if (file_exists($file)) unlink($file); + header("Location: https://www.dpolakovic.space/dead-drop"); + exit; + } + + if (isset($_POST['stashContent'], $_POST['originalW3W'])) { + $input = trim($_POST['originalW3W']); + $hashed_w3w = md5($input); + if (!isValidHash($hashed_w3w)) die('Invalid hash'); + $plaintext = $_POST['stashContent']; + + if (strlen($plaintext) > 4096) { + return ['mode' => 'readonly', 'w3w' => $input, 'status' => 'invalid', 'message' => 'ERROR: Message too long.']; + } + + $filepath = "./Dead-drops/{$hashed_w3w}"; + if (file_exists($filepath)) { + return ['mode' => 'readonly', 'w3w' => $input, 'status' => 'hot']; + } + + $cipher = "AES-256-CBC"; + $key = hash('sha256', $input); + $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher)); + $encrypted = openssl_encrypt($plaintext, $cipher, $key, 0, $iv); + $output = base64_encode($iv . $encrypted); + file_put_contents($filepath, $output); + return ['mode' => 'stashed', 'w3w' => $input]; + } + + if (isset($_POST['inputString'])) { + $input = trim($_POST['inputString']); + if (!validateString($input)) { + return ['mode' => 'readonly', 'w3w' => $input, 'status' => 'invalid', 'message' => 'ERROR: Invalid coordinates format.']; + } + if (!validateStringW3W($input)) { + return ['mode' => 'readonly', 'w3w' => $input, 'status' => 'invalid', 'message' => 'ERROR: Place you are looking for doesn\'t exist.']; + } + $hashed = md5($input); + if (!isValidHash($hashed)) die('Invalid hash'); + $dropPath = './Dead-drops/' . $hashed; + if (file_exists($dropPath)) { + $raw = file_get_contents($dropPath); + $data = base64_decode($raw); + $iv_len = openssl_cipher_iv_length("AES-256-CBC"); + $iv = substr($data, 0, $iv_len); + $ciphertext = substr($data, $iv_len); + $key = hash('sha256', $input); + $decrypted = openssl_decrypt($ciphertext, "AES-256-CBC", $key, 0, $iv); + return [ + 'mode' => 'readonly', + 'w3w' => $input, + 'status' => 'hot', + 'decrypted' => $decrypted + ]; + } else { + return [ + 'mode' => 'readonly', + 'w3w' => $input, + 'status' => 'cold' + ]; + } + } + } + + return ['mode' => 'initial']; +} + +function isValidHash($hash) { + return preg_match('/^[a-f0-9]{32}$/', $hash) === 1; +} + + + + + + + + + + + +function validateString($str) { + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + return false; + } + + if (substr($str, 0, 3) !== "///") { + return false; + } + + $parts = substr($str, 3); + if (substr_count($parts, ".") !== 2) { + return false; + } + + if (!preg_match('/^[a-z]+\.[a-z]+\.[a-z]+$/', $parts)) { + return false; + } + + return true; +} + +function validateStringW3W($str) { + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + return false; + } + + $API_KEY = '747757BO'; + $cleaned = substr($str, 3); + $url = 'https://api.what3words.com/v3/autosuggest?input=' . urlencode($cleaned) . '&key=' . urlencode($API_KEY); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $response = curl_exec($ch); + + if (curl_errno($ch)) { + echo "Curl error: " . curl_error($ch); + return false; + } + + curl_close($ch); + $result = json_decode($response, true); + + if (isset($result['suggestions']) && count($result['suggestions']) > 0) { + foreach ($result['suggestions'] as $suggestion) { + if (strcasecmp($suggestion['words'], $cleaned) === 0) { + return true; + } + } + } + + return false; +} \ No newline at end of file