Author: Jim Winstead (jimwins)
Committer: GitHub (web-flow)
Pusher: jimwins
Date: 2024-09-20T14:22:01-07:00
Commit: Add a subscription form to each group page with radio for standard/di… · php/web-news@fe67cf8 · GitHub
Raw diff: https://github.com/php/web-news/commit/fe67cf8d29785228e2a3f11d018b5f008ae8d79b.diff
Add a subscription form to each group page with radio for standard/digest/nomail (#27)
Changed paths:
A subscribe.php
M group.php
M lib/common.php
M phpcs.xml
M style.css
Diff:
diff --git a/group.php b/group.php
index c8848e6..4884b1c 100644
--- a/group.php
+++ b/group.php
@@ -91,8 +91,34 @@
}
$subscription_address = htmlspecialchars(get_subscribe_address($group));
?>
+ <form class="subscription-form" method="POST" action="/subscribe.php">
+ <input type="hidden" name="group" value="<?= clean($group) ?>">
+ <div>
+ <label for="email">Email address:</label>
+ <input type="email" id="email" name="email" required>
+ </div>
+ <div>
+ <label>
+ <input type="radio" name="type" value="" checked>
+ Standard
+ </label>
+ <label>
+ <input type="radio" name="type" value="digest">
+ Digest
+ </label>
+ <label>
+ <input type="radio" name="type" value="nomail">
+ No emails
+ </label>
+ </div>
+ <div>
+ <button type="submit">
+ Subscribe
+ </button>
+ </div>
+ </form>
<p>
- Subscribe to this list by sending a blank email to
+ You can also subscribe to this list by sending a blank email to
<a href="mailto:<?= $subscription_address ?>">
<?= $subscription_address ?>
</a>
diff --git a/lib/common.php b/lib/common.php
index 8f6f446..7ce3ee8 100644
--- a/lib/common.php
+++ b/lib/common.php
@@ -13,6 +13,91 @@ function error($str)
die();
}
+/* Borrowed from web-php repo. */
+function clean($var)
+{
+ return htmlspecialchars($var, \ENT_QUOTES);
+}
+
+// Try to check that this email address is valid
+function is_emailable_address($email)
+{
+ $email = filter_var($email, FILTER_VALIDATE_EMAIL);
+ // No email, no validation
+ if (!$email) {
+ return false;
+ }
+
+ $host = substr($email, strrpos($email, '@') + 1);
+ // addresses from our mailing-list servers
+ $host_regex = "!(lists\.php\.net|chek[^.*]\.com)!i";
+ if (preg_match($host_regex, $host)) {
+ return false;
+ }
+
+ return true;
+}
+
+// Returns the real IP address of the user
+function i2c_realip()
+{
+ // No IP found (will be overwritten by for
+ // if any IP is found behind a firewall)
+ $ip = false;
+
+ // If HTTP_CLIENT_IP is set, then give it priority
+ if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
+ $ip = $_SERVER["HTTP_CLIENT_IP"];
+ }
+
+ // User is behind a proxy and check that we discard RFC1918 IP addresses
+ // if they are behind a proxy then only figure out which IP belongs to the
+ // user. Might not need any more hackin if there is a squid reverse proxy
+ // infront of apache.
+ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+ // Put the IP's into an array which we shall work with shortly.
+ $ips = explode(", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
+ if ($ip) {
+ array_unshift($ips, $ip);
+ $ip = false;
+ }
+
+ for ($i = 0; $i < count($ips); $i++) {
+ // Skip RFC 1918 IP's 10.0.0.0/8, 172.16.0.0/12 and
+ // 192.168.0.0/16
+ // Also skip RFC 6598 IP's
+ $regex = '/^(?:10|100\.(?:6[4-9]|[7-9]\d|1[01]\d|12[0-7])|172\.(?:1[6-9]|2\d|3[01])|192\.168)\./';
+ if (!preg_match($regex, $ips[$i]) && ip2long($ips[$i])) {
+ $ip = $ips[$i];
+ break;
+ }
+ }
+ }
+
+ // Return with the found IP or the remote address
+ return $ip ?: $_SERVER['REMOTE_ADDR'];
+}
+
+/*
+ This code is used to post data to the central server which
+ can store the data in database and/or mail notices or requests
+ to PHP.net stuff and servers
+*/
+function posttohost($url, $data)
+{
+ $data = http_build_query($data);
+
+ $opts = [
+ 'method' => 'POST',
+ 'header' => 'Content-type: application/x-www-form-urlencoded',
+ 'content' => $data,
+ ];
+
+ $ctx = stream_context_create(['http' => $opts]);
+
+ return file_get_contents($url, false, $ctx);
+}
+
function head($title = "PHP Mailing Lists (PHP News)")
{
header("Content-type: text/html; charset=utf-8");
@@ -216,10 +301,10 @@ function format_date($d)
}
/*
- * Translate a group name to a subscription address for the list. It's almost
+ * Translate a group name to the email address for the list. It's almost
* easy but then we have a bunch of special cases.
*/
-function get_subscribe_address($group)
+function get_list_address($group)
{
$address = str_replace('.', '-', $group); // php.internals -> php-internals
$address = str_replace('php-doc-', 'doc-', $address); // php-doc-fr -> doc-fr
@@ -243,5 +328,10 @@ function get_subscribe_address($group)
$address = $special[$address];
}
- return $address . '+subscribe@lists.php.net';
+ return $address;
+}
+
+function get_subscribe_address($group, $mode = '')
+{
+ return get_list_address($group) . '+subscribe' . ($mode ? '-' . $mode : '') . '@lists.php.net';
}
diff --git a/phpcs.xml b/phpcs.xml
index 7602b0d..e38808b 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -12,5 +12,6 @@
<file>getpart.php</file>
<file>group.php</file>
<file>index.php</file>
+ <file>subscribe.php</file>
<file>lib</file>
</ruleset>
diff --git a/style.css b/style.css
index 92ab9e3..d8f91ce 100644
--- a/style.css
+++ b/style.css
@@ -381,6 +381,12 @@ table.standard th.subr {
.signature a:active { color: #ff9999; }
.signature a:visited { color: #ff66ff; }
+/* Subscription form */
+form.subscription-form {
+ display: flex;
+ gap: 1em;
+}
+
@media screen and (max-width: 760px) {
.welcome {
display: none;
diff --git a/subscribe.php b/subscribe.php
new file mode 100644
index 0000000..fbb620f
--- /dev/null
+++ b/subscribe.php
@@ -0,0 +1,77 @@
+<?php
+
+require 'common.php';
+head("Subscribe to a group");
+echo '<section class="content">';
+
+// No error found yet
+$error = "";
+
+// Check email address
+if (
+ empty($_POST['email']) ||
+ $_POST['email'] == 'user@example.com' ||
+ $_POST['email'] == 'fake@from.net' ||
+ !is_emailable_address($_POST['email'])
+) {
+ $error = "You forgot to specify an email address to be added to the list, or specified an invalid address." .
+ "<br>Please go back and try again.";
+
+// Check if any mailing list was selected
+} elseif (empty($_POST['group'])) {
+ $error = "You need to select a group subscribe to." .
+ "<br>Please go back and try again.";
+
+// Check if type of subscription makes sense
+} elseif (!in_array($_POST['type'], [ '', 'digest', 'nomail' ])) {
+ $error = "The subscription type you specified is not valid." .
+ "<br>Please go back and try again.";
+
+// Seems to be a valid email address
+} else {
+ $remote_addr = i2c_realip();
+ $maillist = get_list_address($_POST['group']);
+ if ($_POST['type'] != '') {
+ $maillist .= '-' . $_POST['type'];
+ }
+
+ if ($maillist) {
+ // Get in contact with main server to subscribe the user
+ $result = posttohost(
+ "https://main.php.net/entry/subscribe.php",
+ [
+ "request" => 'subscribe',
+ "email" => $_POST['email'],
+ "maillist" => $maillist,
+ "remoteip" => $remote_addr,
+ "referer"
+ => 'http' . (@$_SERVER['HTTPS'] ? 's' : '') . '://' . $_SERVER['SERVER_NAME'] .
+ '/' . $_POST['group'],
+ ],
+ );
+
+ // Provide error if unable to subscribe
+ if ($result) {
+ $error = "We were unable to subscribe you due to some technical problems.<br>" .
+ "Please try again later.";
+ }
+ } else {
+ $error = "That's not a group that we can handle.<br>" .
+ "Please try again later.";
+ }
+}
+
+// Give error information or success report
+if (!empty($error)) {
+ echo "<p class=\"formerror\">$error</p>";
+} else {
+ ?>
+ <p>
+ A request has been entered into the mailing list processing queue.
+ You should receive an email at <?php echo clean($_POST['email']); ?> shortly
+ describing how to complete your request.
+ </p>
+ <?php
+}
+echo '</section>';
+foot();