diff options
| author | Gab <24553253+gabrix73@users.noreply.github.com> | 2026-08-16 19:24:16 +0200 |
|---|---|---|
| committer | Gab <24553253+gabrix73@users.noreply.github.com> | 2026-08-16 19:24:16 +0200 |
| commit | 56e296e5875b10ed053cbdedbab08957fce2a461 (patch) | |
| tree | e1c49b328f1fe5142f7e2b27593b0905c5e3668a /index.php | |
| parent | 43fbddf016f94f4ba006d82c9a67dca61b5852a1 (diff) | |
| download | yamnweb-main.tar.gz yamnweb-main.tar.xz yamnweb-main.zip | |
Diffstat (limited to 'index.php')
| -rw-r--r-- | index.php | 52 |
1 files changed, 49 insertions, 3 deletions
@@ -86,6 +86,43 @@ if (empty($_SESSION['csrf_token'])) { $currentCsrfToken = $_SESSION['csrf_token']; /** + * Return remailer names whose public keys are valid today. + * + * @return array<string, bool> Name lookup table. + */ +function getUsableRemailerKeyNames(): array { + static $usableNames = null; + if (is_array($usableNames)) { + return $usableNames; + } + + $usableNames = []; + $keyring = yamnConfig('YAMN_PUBRING', '/opt/yamn-master/pubring.mix'); + if (!is_readable($keyring)) { + return $usableNames; + } + + $today = gmdate('Y-m-d'); + foreach (file($keyring, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [] as $line) { + $parts = preg_split('/\s+/', trim($line)); + if (count($parts) !== 7) { + continue; + } + [$name, , , , , $validFrom, $validUntil] = $parts; + if (!preg_match('/^[a-z0-9_-]+$/', $name) + || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $validFrom) + || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $validUntil)) { + continue; + } + if ($validFrom <= $today && $today <= $validUntil) { + $usableNames[$name] = true; + } + } + + return $usableNames; +} + +/** * Parse remailers from file and return array by type * Entry and Exit can use ANY remailer * Middle should use remailers with specific flags @@ -95,6 +132,7 @@ $currentCsrfToken = $_SESSION['csrf_token']; */ function getRemailers($type) { $remailers = ['*']; // Always include Random option + $usableKeyNames = getUsableRemailerKeyNames(); // Try multiple file locations $files = [ @@ -140,6 +178,7 @@ function getRemailers($type) { // Validate name: lowercase letters, numbers, hyphens only if (!preg_match('/^[a-z0-9-]+$/', $remailerName)) continue; + if (!isset($usableKeyNames[$remailerName])) continue; // Check if last field is 'D' (middle capability flag) $lastField = end($parts); @@ -185,6 +224,9 @@ function resolveRemailer($remailer, $availableRemailers) { $randomIndex = array_rand($candidates); return $candidates[$randomIndex]; } + if (!in_array($remailer, $availableRemailers, true)) { + throw new Exception("Selected remailer is no longer available. Reload the page and choose again."); + } return $remailer; } @@ -246,11 +288,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $middleRemailer = isset($_POST['middle_remailer']) ? filter_var($_POST['middle_remailer'], FILTER_SANITIZE_STRING) : ''; $exitRemailer = isset($_POST['exit_remailer']) ? filter_var($_POST['exit_remailer'], FILTER_SANITIZE_STRING) : ''; $from = isset($_POST['from']) ? filter_var($_POST['from'], FILTER_SANITIZE_STRING) : ''; - $replyTo = isset($_POST['reply_to']) ? filter_var($_POST['reply_to'], FILTER_SANITIZE_STRING) : ''; + $replyTo = isset($_POST['reply_to']) && is_string($_POST['reply_to']) + ? trim($_POST['reply_to']) + : ''; $to = isset($_POST['to']) ? filter_var($_POST['to'], FILTER_SANITIZE_EMAIL) : ''; $subject = isset($_POST['subject']) ? filter_var($_POST['subject'], FILTER_SANITIZE_STRING) : ''; $newsgroups = isset($_POST['newsgroups']) ? filter_var($_POST['newsgroups'], FILTER_SANITIZE_STRING) : ''; - $references = isset($_POST['references']) ? filter_var($_POST['references'], FILTER_SANITIZE_STRING) : ''; + $references = isset($_POST['references']) && is_string($_POST['references']) + ? trim($_POST['references']) + : ''; $data = isset($_POST['data']) ? $_POST['data'] : ''; // Keep original formatting $copies = isset($_POST['copies']) ? intval($_POST['copies']) : 1; @@ -766,7 +812,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { <div class="form-group"><label for="to">Email recipient</label><input type="email" name="to" id="to"><small>Required for email delivery. Leave empty when publishing to a newsgroup.</small></div> <div class="form-group"><label for="subject">Subject <span class="required">*</span></label><input type="text" name="subject" id="subject" required></div> <div class="form-group"><label for="newsgroups">Newsgroup</label><input type="text" name="newsgroups" id="newsgroups" placeholder="misc.test"><small>Optional. When set, the message is routed through the configured Mail-to-News gateway. Leave empty for email.</small></div> - <div class="form-group"><label for="references">References</label><input type="text" name="references" id="references" placeholder="<message-id@example.org>"><small>Optional. Links the article to an existing thread.</small></div> + <div class="form-group"><label for="references">References</label><input type="text" name="references" id="references" maxlength="900" placeholder="<message-id@example.org>"><small>Optional. Enter one or more space-separated Message-IDs, without the <code>References:</code> label. The last ID becomes <code>In-Reply-To</code>.</small></div> <div class="form-group"><label for="data">Message body <span class="required">*</span></label><textarea name="data" id="data" required></textarea> <small>The server creates the encrypted YAMN envelope in memory and sends only that packet through Nym. Remailer queues may take several hours.</small> </div> |
