diff options
| author | arf20 <aruizfernandez05@gmail.com> | 2026-07-01 20:15:42 +0200 |
|---|---|---|
| committer | arf20 <aruizfernandez05@gmail.com> | 2026-07-01 20:15:42 +0200 |
| commit | b7ed54f91c373aef452b3540c8cd352d11305c30 (patch) | |
| tree | a4cb7c87a02e29ee59696ce0f8c245aaa4cee525 | |
| parent | fe649aed998af16df2af646bd0acfed0175f3aa9 (diff) | |
| download | arfnet2-lists-b7ed54f91c373aef452b3540c8cd352d11305c30.tar.gz arfnet2-lists-b7ed54f91c373aef452b3540c8cd352d11305c30.zip | |
Add captcha
| -rw-r--r-- | CaptchasDotNet.php | 309 | ||||
| -rw-r--r-- | index.php | 7 | ||||
| -rw-r--r-- | mlmmj.php | 28 | ||||
| -rw-r--r-- | subscribe.php | 20 |
4 files changed, 357 insertions, 7 deletions
diff --git a/CaptchasDotNet.php b/CaptchasDotNet.php new file mode 100644 index 0000000..7b11409 --- /dev/null +++ b/CaptchasDotNet.php @@ -0,0 +1,309 @@ +<?php +// +// PHP module for easy utilization of the free captchas.net CAPTCHA service +// +// For documentation look at http://captchas.net/ +// https://github.com/captchasDotNet/captchas.net +// +// Written by +// Sebastian Wilhelmi <seppi@seppi.de> and +// Felix Holderied <felix@holderied.de> +// This file is in the public domain. +// + +class CaptchasDotNet +{ + function __construct($client, $secret, + $random_repository = '/tmp/captchasnet-random-strings', + $cleanup_time = 3600, + $alphabet = 'abcdefghijklmnopqrstuvwxyz', + $letters = 6, + $width = 240, + $height = 80, + $color = '000000') + { + $this->__client = $client; + $this->__secret = $secret; + $this->__random_repository = $random_repository; + $this->__cleanup_time = $cleanup_time; + $this->__time_stamp_file = $random_repository . '/__time_stamp__'; + $this->__alphabet = $alphabet; + $this->__letters = $letters; + $this->__width = $width; + $this->__height = $height; + $this->__color = $color; + $this->__random_file = ""; + } + + function __random_string () + { + // The random string shall consist of small letters, big letters + // and digits. + $letters = "abcdefghijklmnopqrstuvwxyz"; + $letters .= strtoupper ($letters) . "0123456789"; + + // The random starts out empty, then 40 random possible characters + // are appended. + $random_string = ''; + for ($i = 0; $i < 40; $i++) + { + $random_string .= $letters[rand (0, strlen ($letters) - 1)]; + } + + // Return the random string. + return $random_string; + } + + // Create a new random string and register it. + function random () + { + // If the repository directory is does not yet exist, create it. + if (!is_dir ($this->__random_repository)) + { + mkdir ($this->__random_repository); + } + + // If the time stamp file does not yet exist, create it. + if (!is_file ($this->__time_stamp_file)) + { + touch ($this->__time_stamp_file); + } + + // Get the current time. + $now = time (); + + // Determine the time, before which to remove random strings. + $cleanup_time = $now - $this->__cleanup_time; + + // If the last cleanup is older than specified, cleanup the + // directory. + if (filemtime ($this->__time_stamp_file) < $cleanup_time) + { + $handle = opendir ($this->__random_repository); + while (true) + { + $filename = readdir ($handle); + if (!$filename) + { + break; + } + if ($filename != '.' && $filename != '..') + { + $filename = $this->__random_repository . '/' . $filename; + if (filemtime ($filename) < $cleanup_time) + { + unlink ($filename); + } + } + } + closedir ($handle); + + touch ($this->__time_stamp_file); + } + + // loop until a valid random string has been found and registered, + // but at most 20 times. If no valid random has been found during + // that time, there is something really wrong. Also show the error + // in the last run. + for ($remaining = 20; $remaining > 0; $remaining--) + { + // generate a new random string. + $random = $this->__random_string (); + + // open a file with the corresponding name in the repository + // directory in such a way, that the creation fails, when the + // file already exists. That should be near to impossible with + // good seeding of the random number generator, but it's better + // to play safe. If this is the last run, show the possible + // error message. + $filename = $this->__random_repository . '/' . $random; + + if ($remaining == 1) + { + $file = fopen ($filename, 'x'); + } + else + { + $file = @fopen ($filename, 'x'); + } + + if ($file) + { + fclose ($file); + break; + } + + // if the file already existed, rerun the loop to try the next + // string. + } + + // return the successfully registered random string. + $this->__random = $random; + return $random; + } + + // + // Generates image-URL Parameters are only atached if different from default + // + function image_url ($random = False, $base = 'http://image.captchas.net/') + { + if (!$random) + { + $random = $this->__random; + } + $image_url = $base; + $image_url .= '?client=' . $this->__client; + $image_url .= '&random=' . $random; + if ($this->__alphabet!='abcdefghijklmnopqrstuvwxyz') {$image_url .= '&alphabet=' . $this->__alphabet;}; + if ($this->__letters!=6) {$image_url .= '&letters=' . $this->__letters;}; + if ($this->__width!=240) {$image_url .= '&width=' . $this->__width;}; + if ($this->__height!=80) {$image_url .= '&height=' . $this->__height;}; + if ($this->__color!='000000') {$image_url .= '&color=' . $this->__color;}; + return $image_url; + } + + // + // Same as image_url but without width and height + // + function audio_url ($random = False, $base = 'http://audio.captchas.net/') + { + if (!$random) + { + $random = $this->__random; + } + $audio_url = $base; + $audio_url .= '?client=' . $this->__client; + $audio_url .= '&random=' . $random; + if ($this->__alphabet!='abcdefghijklmnopqrstuvwxyz') {$audio_url .= '&alphabet=' . $this->__alphabet;}; + if ($this->__letters!=6) {$audio_url .= '&letters=' . $this->__letters;}; + return $audio_url; + } + + // + // Generates complete html-sample with javascript to reload image from + // backup server + // + function image ($random = False, $id = 'captchas.net') + { + $image = <<<EOT + <a href="http://captchas.net"><img + style="border: none; vertical-align: bottom" + id="@ID@" src="@URL@" width="@WIDTH@" height="@HEIGHT@" + alt="The Captcha image" /></a> + <script type="text/javascript"> + <!-- + function captchas_image_reload (imgId) + { + var image_url = document.getElementById(imgId).src; + image_url+= "&"; + document.getElementById(imgId).src = image_url; + } + + function captchas_image_error (image) + { + if (!image.timeout) return true; + image.src = image.src.replace (/^http:\/\/image\.captchas\.net/, + 'http://image.backup.captchas.net'); + return captchas_image_loaded (image); + } + + function captchas_image_loaded (image) + { + if (!image.timeout) return true; + window.clearTimeout (image.timeout); + image.timeout = false; + return true; + } + + var image = document.getElementById ('@ID@'); + image.onerror = function() {return captchas_image_error (image);}; + image.onload = function() {return captchas_image_loaded (image);}; + image.timeout + = window.setTimeout( + "captchas_image_error (document.getElementById ('@ID@'))", + 10000); + image.src = image.src; + //--> + </script> +EOT; + $image = str_replace ('@HEIGHT@', $this->__height, $image); + $image = str_replace ('@WIDTH@', $this->__width, $image); + $image = str_replace ('@ID@', $id, $image); + $image = str_replace ('@URL@', $this->image_url (), $image); + return $image; + } + + function validate ($random) + { + $this->__random = $random; + + $file_name = $this->__random_repository . '/' . $random; + + // Find out, whether the file exists + $result = is_file ($file_name); + + // if the file exists, remember it. + if ($result) + { + $this->__random_file = $file_name; + } + + // the random string was valid, if and only if the corresponding + // file existed. + return $result; + } + + function verify ($input, $random = False) + { + if (!$random) + { + $random = $this->__random; + } + $password_letters = $this->__alphabet; + $password_length = $this->__letters; + + // If the user input has the wrong lenght, it can't be correct. + if (strlen ($input) != $password_length) + { + return False; + } + + // Calculate the MD5 digest of the concatenation of secret key and + // random string. The digest is a hex string. + $encryption_base = $this->__secret . $random; + // This extension is needed for secure use of optional parameters + // In case of standard use we do not append the values, to be + // compatible to existing implementations + if(($password_letters != 'abcdefghijklmnopqrstuvwxyz') || ($password_length != '6')) + { + $encryption_base = $encryption_base . ':' . $password_letters . ':' . $password_length; + } + $digest = md5 ($encryption_base); + + // Check the password according to the rules from the first + // positions of the digest. + for ($pos = 0; $pos < $password_length; $pos++) + { + $letter_num + = hexdec (substr ($digest, 2 * $pos, 2)) % strlen ($password_letters); + + // If the letter at the current position is wrong, the user + // input isn't correct. + if ($input[$pos] != $password_letters[$letter_num]) + { + return False; + } + } + + // if the file exists, remove it. + if ($this->__random_file) + { + unlink ($this->__random_file); + unset ($this->__random_file); + } + + // The user input was correct. + return True; + } + +} @@ -29,14 +29,9 @@ $lists = array_diff($lists, array(".", "..")); } ?> </ul> - <hr> - <h2>Subscription</h2> - <ul> - <li>To subscribe to a list, send a message to list+subscribe@arf20.com or go to https://lists.arf20.com/subscribe.php?list=list</li> - <li>To unsubscribe, send a message to list+unsubscribe@arf20.com or go to https://lists.arf20.com/subscribe.php?list=list</li> - </ul> </div> </div> </main> </body> </html> + @@ -24,6 +24,8 @@ // error_reporting(E_ALL); +require 'CaptchasDotNet.php'; + class mlmmj { var $email; @@ -53,7 +55,9 @@ class mlmmj !isset($_POST["mailinglist"]) && !isset($_POST["job"]) && !isset($_POST["redirect_success"]) && - !isset($_POST["redirect_failure"])) + !isset($_POST["redirect_failure"]) && + !isset($_POST["random"])) && + !isset($_POST["captcha"])) { $this->errors = TRUE; if(isset($_POST["redirect_failure"])) { @@ -64,6 +68,28 @@ class mlmmj die("An error occurred. Please check contrib/web/php-user/README for details."); } else { + $captchas = new CaptchasDotNet ('arf20', '7QOD8AEp5n9ib5bp', + '/tmp/captchasnet-random-strings','3600', + 'abcdefghkmnopqrstuvwxyz','6', + '240','80','000088'); + + // Check the random string to be valid and return an error message + // otherwise. + if (!$captchas->validate ($random_string)) + { + $this->error( + "The session key (random) does not exist, please go back and reload form.<br/>" + ."In case you are the administrator of this page, " + ."please check if random keys are stored correct.<br/>" + ."See http://captchas.net/sample/php/ 'Problems with save mode'"); + } + // Check, that the right CAPTCHA password has been entered and + // return an error message otherwise. + elseif (!$captchas->verify ($password)) + { + $this->error("You entered the wrong password. Aren't you human? Please use back button and reload."; + } + if ($this->is_email($_POST["email"])) $this->email = $_POST["email"]; else diff --git a/subscribe.php b/subscribe.php index f60c15b..f2e9d56 100644 --- a/subscribe.php +++ b/subscribe.php @@ -1,5 +1,12 @@ <?php +require 'CaptchasDotNet.php'; + +$captchas = new CaptchasDotNet ('arf20', '7QOD8AEp5n9ib5bp', + '/tmp/captchasnet-random-strings','3600', + 'abcdefghkmnopqrstuvwxyz','6', + '240','80','000088'); + if (!isset($_GET["list"]) || empty($_GET["list"])) { die("List required"); } @@ -34,6 +41,8 @@ $domain = "arf20.com" <input name="job" type="hidden" value="subscribe"> <input name="redirect_failure" type="hidden" value="/error.html"> <input name="redirect_success" type="hidden" value="/"> + <input type="hidden" name="random" value="<?= $captchas->random () ?>" /> + <input name="captcha" size="6" /> <br><input type="submit" value="Subscribe"> </form> @@ -45,9 +54,20 @@ $domain = "arf20.com" <input name="job" type="hidden" value="unsubscribe"> <input name="redirect_failure" type="hidden" value="/error.html"> <input name="redirect_success" type="hidden" value="/"> + <input type="hidden" name="random" value="<?= $captchas->random () ?>" /> + <input name="captcha" size="6" /> <br><input type="submit" value="Subscribe"> </form> + <?= $captchas->image () ?> <a href="javascript:captchas_image_reload('captchas.net')">Reload Image</a> + + <hr> + <h2>E-mail based subscription</h2> + <ul> + <li>To subscribe to <?php echo $list; ?>, send a message to <?php echo $list; ?>+subscribe@arf20.com</li> + <li>To unsubscribe, send a message to <?php echo $list; ?>+unsubscribe@arf20.com</li> + </ul> </div> </main> </body> </html> + |
