diff options
Diffstat (limited to 'addons')
-rw-r--r-- | addons/copyable_captcha.php | 104 | ||||
-rw-r--r-- | addons/funnyquestion.php | 160 | ||||
-rw-r--r-- | addons/index.html | 1 | ||||
-rw-r--r-- | addons/recaptcha.php | 136 |
4 files changed, 401 insertions, 0 deletions
diff --git a/addons/copyable_captcha.php b/addons/copyable_captcha.php new file mode 100644 index 0000000..8f136d9 --- /dev/null +++ b/addons/copyable_captcha.php @@ -0,0 +1,104 @@ +<?php + +/** + * Copyable Captha plugin + * Copyright (C) 2016 artoodetoo + * Special thanks to Visman for his help + * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher + */ + +class addon_copyable_captcha extends flux_addon +{ + var $lang; + var $styles; + var $spans; + + function register($manager) + { + global $pun_user; + + if (!$pun_user['is_guest']) return; + + $manager->bind('register_after_validation', array($this, 'hook_register_after_validation')); + $manager->bind('register_before_header', array($this, 'hook_register_before_header')); + $manager->bind('register_before_submit', array($this, 'hook_register_before_submit')); + } + + function load_lang() + { + global $pun_user; + + if (isset($this->lang)) return; + + $user_lang = file_exists(PUN_ROOT.'lang/'.$pun_user['language'].'/copyable_captcha.php') + ? $pun_user['language'] + : 'English'; + require PUN_ROOT.'lang/'.$user_lang.'/copyable_captcha.php'; + + $this->lang = $lang_copyable_captcha; + } + + function hook_register_after_validation() + { + global $errors, $cookie_name, $cookie_seed; + + if (isset($_POST['req_word']) && isset($_COOKIE[$cookie_name.'_captcha']) && substr_count($_COOKIE[$cookie_name.'_captcha'], '-') === 1) { + list($hash, $time) = explode('-', $_COOKIE[$cookie_name.'_captcha']); + $word = $_POST['req_word']; + if ((int)$time <= time() - 120 || $hash !== sha1(strtolower($word).$cookie_seed.'secret'.$time)) { + $this->load_lang(); + $errors[] = $this->lang['Captcha error']; + } + } else { + $this->load_lang(); + $errors[] = $this->lang['Captcha error']; + } + } + + + function hook_register_before_header() + { + global $required_fields, $errors, $cookie_name, $cookie_seed; + + $this->load_lang(); + $required_fields['req_word'] = $this->lang['Captcha']; + + $time = time(); + $word = random_pass(mt_rand(4, 6)); + $hash = sha1(strtolower($word).$cookie_seed.'secret'.$time); + forum_setcookie($cookie_name.'_captcha', $hash.'-'.$time, $time + 120); + + $array = str_split($word); + $mixin = random_pass(mt_rand(1, 3)); + $i = -1; + $this->styles = ''; + foreach (str_split($mixin) as $ch) { + $i = mt_rand($i+1, count($array)); + array_splice($array, $i, 0, $ch); + $this->styles .= '.masq i:nth-child('.($i + 1).'){display:none;} '; + } + $this->spans = '<i>'.implode('</i><i>', $array).'</i>'; + } + + + function hook_register_before_submit() + { + global $lang_common; + + $this->load_lang(); + +?> + <div class="inform"> + <fieldset> + <legend><?php echo $this->lang['Captcha legend'] ?></legend> + <div class="infldset"> + <style> .masq i {font-style:normal;} <?php echo $this->styles ?></style> + <p><?php echo sprintf($this->lang['Captcha info'], $this->spans) ?></p> + <label class="required"><strong><?php echo $this->lang['Captcha'] ?> <span><?php echo $lang_common['Required'] ?></span></strong><br /><input type="text" name="req_word" size="25" maxlength="25" /><br /></label> + </div> + </fieldset> + </div> +<?php + + } +} diff --git a/addons/funnyquestion.php b/addons/funnyquestion.php new file mode 100644 index 0000000..e3cd4e9 --- /dev/null +++ b/addons/funnyquestion.php @@ -0,0 +1,160 @@ +<?php + +if (!defined('PUN')) { + exit; +} + +class addon_funnyquestion extends flux_addon +{ + + public function __construct() + { + global $funnyquestion_disabled, $funnyquestion_hash, $funny_questions, $funnyquestion_timeout, $funnyquestion_remember, $funnyquestion_wait, $pun_user, $lang_funnyquestion; + + !isset($funnyquestion_disabled) && $funnyquestion_disabled = false; + !isset($funnyquestion_hash) && $funnyquestion_hash = dirname(__FILE__); + !isset($funny_questions) && $funny_questions = array( + 'What is the Ultimate Answer to the Ultimate Question of Life, The Universe, and Everything?' => '42' + ); + !isset($funnyquestion_timeout) && $funnyquestion_timeout = 3600; + !isset($funnyquestion_remember) && $funnyquestion_remember = 3600 * 24; + !isset($funnyquestion_wait) && $funnyquestion_wait = 2; + + if (file_exists(PUN_ROOT . 'lang/' . $pun_user['language'] . '/funnyquestion.php')) { + require PUN_ROOT . 'lang/' . $pun_user['language'] . '/funnyquestion.php'; + } else { + require PUN_ROOT . 'lang/English/funnyquestion.php'; + } + } + + /** + * @param flux_addon_manager $manager + */ + public function register($manager) + { + $manager->bind('register_before_submit', array($this, 'print_funnyquestion')); + $manager->bind('quickpost_before_submit', array($this, 'print_funnyquestion')); + $manager->bind('post_before_submit', array($this, 'print_funnyquestion')); + $manager->bind('register_before_validation', array($this, 'set_error_on_check_funnyquestion')); + $manager->bind('post_before_validation', array($this, 'set_error_on_check_funnyquestion')); + } + + public function print_funnyquestion() + { + echo $this->get_funnyquestion(); + } + + public function set_error_on_check_funnyquestion() + { + global $errors, $lang_funnyquestion; + $this->check_funnyquestion() || $errors[] = $lang_funnyquestion['wrong-answer']; + } + + /** + * @param string $answer + * @return string + */ + private function normalize_funnyanswer($answer) + { + return preg_replace('/[^a-z0-9]/', '', strtolower($answer)); + } + + private function set_funnycookie() + { + global $funnyquestion_hash, $funnyquestion_remember; + + $time = time(); + forum_setcookie('funnyquestion_hash', sha1($time . get_remote_address() . $funnyquestion_hash), + $time + $funnyquestion_remember); + forum_setcookie('funnyquestion_time', $time, $time + $funnyquestion_remember); + } + + /** + * @return bool + */ + private function has_funnycookie() + { + global $funnyquestion_hash, $funnyquestion_remember; + + return (!empty($_COOKIE['funnyquestion_hash']) && !empty($_COOKIE['funnyquestion_time']) + && time() - $funnyquestion_remember <= $_COOKIE['funnyquestion_time'] + && sha1($_COOKIE['funnyquestion_time'] . get_remote_address() . $funnyquestion_hash) == $_COOKIE['funnyquestion_hash']); + } + + /** + * @return string + */ + private function get_funnyquestion() + { + global $funnyquestion_disabled, $funnyquestion_hash, $funny_questions, $lang_funnyquestion, $lang_common, $pun_user; + + if ($funnyquestion_disabled || !$pun_user['is_guest'] || $this->has_funnycookie()) { + return ''; + } + + $time = time(); + $question = array_rand($funny_questions); + # make sure the user is not able to tell us the question to answer + $hash = sha1($time . $question . $funnyquestion_hash); + + return '<div class="inform"> + <fieldset> + <legend>' . $lang_funnyquestion['question-label'] . '</legend> + <div class="infldset"> + <input type="hidden" name="funnyquestion_time" value="' . $time . '" /> + <input type="hidden" name="funnyquestion_hash" value="' . $hash . '" /> + <label class="required"> + <strong>' . $question . '<span>' . $lang_common['Required'] . '</span></strong><br /> + <input type="text" name="funny_answer" value="" size="50" /><br /> + </label> + </div> + </fieldset> + </div>'; + } + + /** + * @return bool + */ + private function check_funnyquestion() + { + global $funnyquestion_disabled, $funnyquestion_hash, $funnyquestion_timeout, $funnyquestion_wait, $funny_questions, $pun_user; + + if ($funnyquestion_disabled || !$pun_user['is_guest'] || $this->has_funnycookie()) { + return true; + } + + if (!empty($_POST['funnyquestion_time']) + && !empty($_POST['funnyquestion_hash']) + && !empty($_POST['funny_answer']) + ) { + $now = time(); + $time = $_POST['funnyquestion_time']; + $hash = $_POST['funnyquestion_hash']; + $user_answer = $this->normalize_funnyanswer($_POST['funny_answer']); + } else { + return false; + } + + if ($now - $time > $funnyquestion_timeout) { + return false; + } elseif ($now - $time < $funnyquestion_wait) { + return false; + } + + foreach ($funny_questions as $question => $answers) { + if (!is_array($answers)) { + $answers = array($answers); + } + foreach ($answers as $answer) { + if ($this->normalize_funnyanswer($answer) == $user_answer + && $hash == sha1($time . $question . $funnyquestion_hash) + ) { + $this->set_funnycookie(); + return true; + } + } + } + + return false; + } +} diff --git a/addons/index.html b/addons/index.html new file mode 100644 index 0000000..cf1a99a --- /dev/null +++ b/addons/index.html @@ -0,0 +1 @@ +<html><head><title>.</title></head><body>.</body></html>
diff --git a/addons/recaptcha.php b/addons/recaptcha.php new file mode 100644 index 0000000..668de1c --- /dev/null +++ b/addons/recaptcha.php @@ -0,0 +1,136 @@ +<?php + +class addon_recaptcha extends flux_addon +{ + function register($manager) + { + global $pun_user; + + if (!$this->is_configured()) return; + + $this->get_language(); + + if ($this->enabled_location('register')) + { + $manager->bind('register_after_validation', array($this, 'hook_after_validation')); + $manager->bind('register_before_submit', array($this, 'hook_before_submit')); + } + + if ($this->enabled_location('login')) + { + $manager->bind('login_after_validation', array($this, 'hook_after_validation')); + $manager->bind('login_before_submit', array($this, 'hook_before_submit')); + } + + if ($this->enabled_location('guestpost') && $pun_user['is_guest']) + { + $manager->bind('post_after_validation', array($this, 'hook_after_validation')); + $manager->bind('post_before_submit', array($this, 'hook_before_submit')); + $manager->bind('quickpost_before_submit', array($this, 'hook_before_submit')); + } + } + + function is_configured() + { + global $pun_config; + + return !empty($pun_config['recaptcha_enabled']) && !empty($pun_config['recaptcha_site_key']) && !empty($pun_config['recaptcha_secret_key']); + } + + function enabled_location($page) + { + global $pun_config; + + return !empty($pun_config['recaptcha_location_'.$page]); + } + + function get_language() + { + global $pun_user; + + if (file_exists(PUN_ROOT.'lang/'.$pun_user['language'].'/recaptcha_addon.php')) + require PUN_ROOT.'lang/'.$pun_user['language'].'/recaptcha_addon.php'; + else + require PUN_ROOT.'lang/English/recaptcha_addon.php'; + } + + function hook_after_validation() + { + global $errors, $lang_recaptcha; + + if (empty($errors) && !$this->verify_user_response()) + { + $errors[] = $lang_recaptcha['Error']; + } + } + + function hook_before_submit() + { + global $pun_config, $lang_recaptcha; + + $site_key = $pun_config['recaptcha_site_key']; + + ?> + <div class="inform"> + <fieldset> + <legend><?= $lang_recaptcha['Human']; ?></legend> + <div class="infldset"> + <p><?= $lang_recaptcha['Prove']; ?></p> + <script src="https://www.google.com/recaptcha/api.js"></script> + <div class="g-recaptcha" data-sitekey="<?php echo pun_htmlspecialchars($site_key) ?>"></div> + </div> + </fieldset> + </div> + <?php + } + + function verify_user_response() + { + global $pun_config; + + if (empty($_POST['g-recaptcha-response'])) return false; + + $secret = $pun_config['recaptcha_secret_key']; + $response = $_POST['g-recaptcha-response']; + $ip = get_remote_address(); + + $query = "secret=$secret&response=$response&remoteip=$ip"; + $url = "https://www.google.com/recaptcha/api/siteverify?$query"; + + $response = $this->send_request($url); + + return strpos($response, '"success": true') !== false; + } + + function send_request($url) + { + if (function_exists('curl_version')) + return $this->send_curl_request($url); + else + return $this->get_remote_file($url); + } + + function send_curl_request($url) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + $response = curl_exec($ch); + curl_close($ch); + + return $response; + } + + function get_remote_file($url) + { + global $lang_recaptcha; + + $response = file_get_contents($url); + + if ($response === false) + throw new Exception($lang_recaptcha['API error']); + + return $response; + } +} |