1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
<?php
// /var/www/mail2usenet/send.php
// Hands the post to Postfix transport “mail2news”, enforcing Ed25519 signature.
$required = [
'from', 'newsgroups', 'subject', 'xhashcash', 'x-ed25519-sig', 'message'
];
// Collect POST values
$data = [];
foreach ($_POST as $k => $v) $data[$k] = trim($v);
// Check required fields
$missing = array_filter($required, fn($f) => empty($data[$f] ?? ''));
if ($missing) {
showError(
'Missing required fields: ' . implode(', ', $missing) .
'. Remember: you must click <em>Sign Message</em> on the Digital Signature tab before sending.'
);
}
// Limit newsgroups to 3
$groups = array_slice(
array_filter(array_map('trim', explode(',', $data['newsgroups']))),
0, 3
);
$data['newsgroups'] = implode(', ', $groups);
// Build raw email
$hdr = [];
$hdr[] = 'From: ' . $data['from'];
$hdr[] = 'To: mail2news@localhost'; // dummy for sendmail -t
$hdr[] = 'Newsgroups: ' . $data['newsgroups'];
$hdr[] = 'Subject: ' . $data['subject'];
if (!empty($data['references'])) $hdr[] = 'References: ' . $data['references'];
$hdr[] = 'X-Hashcash: ' . $data['xhashcash'];
$hdr[] = 'X-Ed25519-Sig: ' . $data['x-ed25519-sig'];
if (!empty($data['x-ed25519-pub'])) {
$hdr[] = 'X-Ed25519-Pub: ' . $data['x-ed25519-pub'];
}
$hdr[] = 'X-No-Archive: Yes';
$hdr[] = 'Mime-Version: 1.0';
$hdr[] = 'Content-Type: text/plain; charset=UTF-8';
$hdr[] = 'Content-Transfer-Encoding: 7bit';
$hdr[] = ''; // blank line before body
$raw = implode("\r\n", $hdr) . "\r\n" . $data['message'] . "\r\n";
// Send via sendmail using the custom transport
$sendmail = '/usr/sbin/sendmail';
$cmd = escapeshellcmd($sendmail) . ' -i -oTransport=mail2news -t';
$descriptors = [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
];
$proc = proc_open($cmd, $descriptors, $pipes);
if (!is_resource($proc)) showError('Failed to invoke sendmail.');
fwrite($pipes[0], $raw);
fclose($pipes[0]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$code = proc_close($proc);
if ($code !== 0) {
showError('Sendmail error (code ' . $code . '):<br>' . nl2br(htmlspecialchars($stderr)));
}
// ------------------ success page ------------------
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Post Sent</title>
<style>
body { font-family:sans-serif; text-align:center; padding:50px; }
a.button { display:inline-block; margin-top:20px; padding:10px 20px;
background:#4caf50; color:#fff; border-radius:4px; text-decoration:none; }
a.button:hover { background:#45a049; }
</style>
</head>
<body>
<h1>Message Sent Successfully</h1>
<p>Your article was handed off to <code>mail2news</code> and should appear in the newsgroups soon.</p>
<a class="button" href="https://m2usenet.virebent.art">Return to Home</a>
</body>
</html>
<?php
// -------- helper --------
function showError(string $msg): void {
http_response_code(400);
?>
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="UTF-8"><title>Error</title>
<style>
body { font-family:sans-serif; text-align:center; padding:50px; color:#d00; }
a { color:#337ab7; }
</style>
</head><body>
<h1>Submission Error</h1>
<p><?= $msg ?></p>
<p><a href="https://m2usenet.virebent.art">Return to Home</a></p>
</body></html>
<?php
exit;
}
?>
|