Author: Jim Winstead (jimwins)
Committer: GitHub (web-flow)
Pusher: jimwins
Date: 2024-09-20T14:22:01-07:00

Commit: 
https://github.com/php/web-news/commit/fe67cf8d29785228e2a3f11d018b5f008ae8d79b
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 . '+subscr...@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'] == 'u...@example.com' ||
+    $_POST['email'] == 'f...@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();

Reply via email to