From f0f9cee2ff3174db24af6eca2bef740844b423b9 Mon Sep 17 00:00:00 2001 From: ale <ale@incal.net> Date: Sat, 25 Jul 2015 18:33:47 +0100 Subject: [PATCH] [auto] Plugin: wp-recaptcha 4.1 --- wp-content/plugins/wp-recaptcha/readme.txt | 37 +- wp-content/plugins/wp-recaptcha/recaptcha.php | 1014 +++++++---------- .../plugins/wp-recaptcha/recaptchalib.php | 331 ++---- wp-content/plugins/wp-recaptcha/settings.php | 119 +- wp-content/plugins/wp-recaptcha/uninstall.php | 3 - wp-content/plugins/wp-recaptcha/wp-plugin.php | 55 +- .../plugins/wp-recaptcha/wp-recaptcha.php | 9 +- 7 files changed, 611 insertions(+), 957 deletions(-) diff --git a/wp-content/plugins/wp-recaptcha/readme.txt b/wp-content/plugins/wp-recaptcha/readme.txt index 206a99eab..12b18f40c 100644 --- a/wp-content/plugins/wp-recaptcha/readme.txt +++ b/wp-content/plugins/wp-recaptcha/readme.txt @@ -1,49 +1,38 @@ === Plugin Name === Contributors: recaptchanet -Tags: comments, registration, recaptcha, antispam, mailhide, captcha +Tags: comments, registration, recaptcha, antispam, captcha Requires at least: 2.7 Tested up to: 2.9.1 -Stable tag: 3.2 +Stable tag: 4.1 -Integrates reCAPTCHA anti-spam methods with WordPress including comment, registration, and email spam protection. +Integrates reCAPTCHA anti-spam methods with WordPress including comment and registration spam protection. == Description == -= Notice = +What is reCAPTCHA? -If anyone is interested in taking up development of this plugin, please contact me at blaenk@gmail.com. I would be glad to provide access to the plugin repository. Preferably someone who has experience with the WP and WP multisite APIs (primarily their authorization and options APIs). +reCAPTCHA is a free CAPTCHA service that protects your site against spam, malicious registrations and other forms of attacks where computers try to disguise themselves as a human; a CAPTCHA is a Completely Automated Public Turing test to tell Computers and Human Apart. reCAPTCHA comes in the form of a widget that you can easily add to your blog, forum, registration form, etc. -If you would like to simply contribute patches, you are welcome to do so at the [github repository](https://github.com/blaenk/wp-recaptcha). - -Otherwise, if anyone encounters issues with this plugin, you might want to give [this one](http://wordpress.org/extend/plugins/bwp-recaptcha/) a try. - -= What is reCAPTCHA? = - -[reCAPTCHA](http://recaptcha.net/ "reCAPTCHA") is an anti-spam method originating from [Carnegie Mellon University](http://www.cmu.edu/index.shtml "Carnegie Mellon University"), then acquired by [Google](http://www.google.com/recaptcha) which uses [CAPTCHAs](http://recaptcha.net/captcha.html "CAPTCHA") in a [genius way](http://recaptcha.net/learnmore.html "How Does it Work? - reCAPTCHA"). Instead of randomly generating useless characters which users grow tired of continuosly typing in, risking the possibility that spammers will eventually write sophisticated spam bots which use [OCR](http://en.wikipedia.org/wiki/Optical_character_recognition "Optical Character Recognition - Wikipedia") libraries to read the characters, reCAPTCHA uses a different approach. - -The world is in the process of digitizing books by use of automated machines which employ the use of Optical Character Recognition software. Sometimes the certain words cannot be read by the software. reCAPTCHA uses a combination of these words, further distorts them, and then constructs a CAPTCHA image. After a certain percentage of users solve the 'unknown' word the same way, it is assumed that it is the correct spelling of the word. This helps digitize books, giving users a ***reason*** to solve reCAPTCHA forms. Because the industry level scanners and OCR software which are used to digitize the books can't read the words with which the CAPTCHAs are constructed, it is safe to assume that in-house spam-bot OCR techniques will not be able to bypass the resulting CAPTCHA, which is a further distortion of the unreadable word. - -reCAPTCHA is probably the most popular and widely accepted CAPTCHA systems by both end-users and site-owners. It is used by such sites prominent sites as [Facebook](http://www.facebook.com), [Twitter](http://www.twitter.com), to the Average Joe's little blog out there on the corner of the Internet. - -It is accessible by everyone. If the user has trouble reading the CAPTCHA challenge, he or she has the option of requesting a new one. If this does not help, there is also an audio challenge which users may use. +In addition to protecting your site, reCAPTCHA also helps us digitize old books and newspapers, transcribe street numbers and solve hard AI problems. [Learn how reCAPTCHA works](http://www.google.com/recaptcha) and join our [forum](https://groups.google.com/forum/#!forum/recaptcha). == Installation == To install in regular WordPress and [WordPress MultiSite](http://codex.wordpress.org/Create_A_Network): 1. Upload the `wp-recaptcha` folder to the `/wp-content/plugins/` directory -1. Activate the plugin through the `Plugins` menu in WordPress -1. Get the reCAPTCHA keys [here](http://recaptcha.net/api/getkey?domain=www.blaenkdenum.com&app=wordpress "reCAPTCHA API keys") and/or the MailHide keys [here](http://mailhide.recaptcha.net/apikey "MailHide keys") +2. Activate the plugin through the `Plugins` menu in WordPress +3. Get the reCAPTCHA keys [here](https://www.google.com/recaptcha/admin#whyrecaptcha). == Requirements == -* You need the reCAPTCHA keys [here](http://recaptcha.net/api/getkey?domain=www.blaenkdenum.com&app=wordpress "reCAPTCHA API keys") and/or the MailHide keys [here](http://mailhide.recaptcha.net/apikey "MailHide keys") -* If you plan on using MailHide, you will need to have the [mcrypt](http://php.net/mcrypt "mcrypt") PHP module loaded (*Most servers do*) -* If you turn on XHTML 1.0 Compliance you and your users will need to have Javascript enabled to see and complete the reCAPTCHA form +* You need the reCAPTCHA keys [here](https://www.google.com/recaptcha/admin#whyrecaptcha). * Your theme must have a `do_action('comment_form', $post->ID);` call right before the end of your form (*Right before the closing form tag*). Most themes do. == ChangeLog == += Version 4.0 +* Upgrade to reCAPTCHA V2. +* Increase supported languages to 40+. = Version 3.2 * Transferred ownership back to Google = Version 3.1.6 = @@ -134,4 +123,4 @@ CAPTCHAs offer great protection against abuse from automated programs. While it == Screenshots == 1. The reCAPTCHA Settings -2. The MailHide Settings +2. Comments page with reCAPTCHA diff --git a/wp-content/plugins/wp-recaptcha/recaptcha.php b/wp-content/plugins/wp-recaptcha/recaptcha.php index 8b6a414ec..40541392b 100644 --- a/wp-content/plugins/wp-recaptcha/recaptcha.php +++ b/wp-content/plugins/wp-recaptcha/recaptcha.php @@ -1,601 +1,471 @@ <?php +/** + * This is a PHP library that handles calling reCAPTCHA. + * - Documentation and latest version + * https://developers.google.com/recaptcha/docs/php + * - Get a reCAPTCHA API Key + * https://www.google.com/recaptcha/admin/create + * - Discussion group + * http://groups.google.com/group/recaptcha + * + * @link http://www.google.com/recaptcha + */ require_once('wp-plugin.php'); -if (!class_exists('reCAPTCHA')) { - class reCAPTCHA extends WPPlugin { - // member variables - private $saved_error; - - // php 4 constructor - function reCAPTCHA($options_name) { - $args = func_get_args(); - call_user_func_array(array(&$this, "__construct"), $args); - } - - // php 5 constructor - function __construct($options_name) { - parent::__construct($options_name); - - $this->register_default_options(); - - // require the recaptcha library - $this->require_library(); - - // register the hooks - $this->register_actions(); - $this->register_filters(); - } - - function register_actions() { - // load the plugin's textdomain for localization - add_action('init', array(&$this, 'load_textdomain')); - - // styling - add_action('wp_head', array(&$this, 'register_stylesheets')); // make unnecessary: instead, inform of classes for styling - add_action('admin_head', array(&$this, 'register_stylesheets')); // make unnecessary: shouldn't require styling in the options page - - if ($this->options['show_in_registration']) - add_action('login_head', array(&$this, 'registration_style')); // make unnecessary: instead use jQuery and add to the footer? - - // options - register_activation_hook(WPPlugin::path_to_plugin_directory() . '/wp-recaptcha.php', array(&$this, 'register_default_options')); // this way it only happens once, when the plugin is activated - add_action('admin_init', array(&$this, 'register_settings_group')); - - // only register the hooks if the user wants recaptcha on the registration page - if ($this->options['show_in_registration']) { - // recaptcha form display - if ($this->is_multi_blog()) - add_action('signup_extra_fields', array(&$this, 'show_recaptcha_in_registration')); - else - add_action('register_form', array(&$this, 'show_recaptcha_in_registration')); - } +if (class_exists('ReCAPTCHAPlugin')) +{ + return; +} + +class ReCAPTCHAPlugin extends WPPlugin +{ + private $_saved_error; + private $_reCaptchaLib; + + /** + * Php 4 Constructor. + * + * @param string $options_name + */ + function ReCAPTCHAPlugin($options_name) { + $args = func_get_args(); + call_user_func_array(array(&$this, "__construct"), $args); + } + + /** + * Php 5 Constructor. + * + * @param string $options_name + */ + function __construct($options_name) { + parent::__construct($options_name); + $this->register_default_options(); - // only register the hooks if the user wants recaptcha on the comments page - if ($this->options['show_in_comments']) { - add_action('comment_form', array(&$this, 'show_recaptcha_in_comments')); - - // recaptcha comment processing (look into doing all of this with AJAX, optionally) - add_action('wp_head', array(&$this, 'saved_comment'), 0); - add_action('preprocess_comment', array(&$this, 'check_comment'), 0); - add_action('comment_post_redirect', array(&$this, 'relative_redirect'), 0, 2); - } - - // administration (menus, pages, notifications, etc.) - add_filter("plugin_action_links", array(&$this, 'show_settings_link'), 10, 2); - - add_action('admin_menu', array(&$this, 'add_settings_page')); - - // admin notices - add_action('admin_notices', array(&$this, 'missing_keys_notice')); - } - - function register_filters() { - // only register the hooks if the user wants recaptcha on the registration page - if ($this->options['show_in_registration']) { - // recaptcha validation - if ($this->is_multi_blog()) - add_filter('wpmu_validate_user_signup', array(&$this, 'validate_recaptcha_response_wpmu')); - else - add_filter('registration_errors', array(&$this, 'validate_recaptcha_response')); - } - } - - function load_textdomain() { - load_plugin_textdomain('recaptcha', false, 'languages'); - } - - // set the default options - function register_default_options() { - if ($this->options) - return; - - $option_defaults = array(); - - $old_options = WPPlugin::retrieve_options("recaptcha"); - - if ($old_options) { - $option_defaults['public_key'] = $old_options['pubkey']; // the public key for reCAPTCHA - $option_defaults['private_key'] = $old_options['privkey']; // the private key for reCAPTCHA - - // placement - $option_defaults['show_in_comments'] = $old_options['re_comments']; // whether or not to show reCAPTCHA on the comment post - $option_defaults['show_in_registration'] = $old_options['re_registration']; // whether or not to show reCAPTCHA on the registration page - - // bypass levels - $option_defaults['bypass_for_registered_users'] = ($old_options['re_bypass'] == "on") ? 1 : 0; // whether to skip reCAPTCHAs for registered users - $option_defaults['minimum_bypass_level'] = $old_options['re_bypasslevel']; // who doesn't have to do the reCAPTCHA (should be a valid WordPress capability slug) - - if ($option_defaults['minimum_bypass_level'] == "level_10") { - $option_defaults['minimum_bypass_level'] = "activate_plugins"; - } - - // styling - $option_defaults['comments_theme'] = $old_options['re_theme']; // the default theme for reCAPTCHA on the comment post - $option_defaults['registration_theme'] = $old_options['re_theme_reg']; // the default theme for reCAPTCHA on the registration form - $option_defaults['recaptcha_language'] = $old_options['re_lang']; // the default language for reCAPTCHA - $option_defaults['xhtml_compliance'] = $old_options['re_xhtml']; // whether or not to be XHTML 1.0 Strict compliant - $option_defaults['comments_tab_index'] = $old_options['re_tabindex']; // the default tabindex for reCAPTCHA - $option_defaults['registration_tab_index'] = 30; // the default tabindex for reCAPTCHA - - // error handling - $option_defaults['no_response_error'] = $old_options['error_blank']; // message for no CAPTCHA response - $option_defaults['incorrect_response_error'] = $old_options['error_incorrect']; // message for incorrect CAPTCHA response - } - - else { - // keys - $option_defaults['public_key'] = ''; // the public key for reCAPTCHA - $option_defaults['private_key'] = ''; // the private key for reCAPTCHA - - // placement - $option_defaults['show_in_comments'] = 1; // whether or not to show reCAPTCHA on the comment post - $option_defaults['show_in_registration'] = 1; // whether or not to show reCAPTCHA on the registration page - - // bypass levels - $option_defaults['bypass_for_registered_users'] = 1; // whether to skip reCAPTCHAs for registered users - $option_defaults['minimum_bypass_level'] = 'read'; // who doesn't have to do the reCAPTCHA (should be a valid WordPress capability slug) - - // styling - $option_defaults['comments_theme'] = 'red'; // the default theme for reCAPTCHA on the comment post - $option_defaults['registration_theme'] = 'red'; // the default theme for reCAPTCHA on the registration form - $option_defaults['recaptcha_language'] = 'en'; // the default language for reCAPTCHA - $option_defaults['xhtml_compliance'] = 0; // whether or not to be XHTML 1.0 Strict compliant - $option_defaults['comments_tab_index'] = 5; // the default tabindex for reCAPTCHA - $option_defaults['registration_tab_index'] = 30; // the default tabindex for reCAPTCHA - - // error handling - $option_defaults['no_response_error'] = '<strong>ERROR</strong>: Please fill in the reCAPTCHA form.'; // message for no CAPTCHA response - $option_defaults['incorrect_response_error'] = '<strong>ERROR</strong>: That reCAPTCHA response was incorrect.'; // message for incorrect CAPTCHA response - } - - // add the option based on what environment we're in - WPPlugin::add_options($this->options_name, $option_defaults); - } - // require the recaptcha library - function require_library() { - require_once($this->path_to_plugin_directory() . '/recaptchalib.php'); - } - - // register the settings - function register_settings_group() { - register_setting("recaptcha_options_group", 'recaptcha_options', array(&$this, 'validate_options')); - } - - // todo: make unnecessary - function register_stylesheets() { - $path = WPPlugin::url_to_plugin_directory() . '/recaptcha.css'; - - echo '<link rel="stylesheet" type="text/css" href="' . $path . '" />'; - } - - // stylesheet information - // todo: this 'hack' isn't nice, try to figure out a workaround - function registration_style() { - $width = 0; // the width of the recaptcha form - - // every theme is 358 pixels wide except for the clean theme, so we have to programmatically handle that - if ($this->options['registration_theme'] == 'clean') - $width = 485; - else - $width = 360; - - echo <<<REGISTRATION - <script type="text/javascript"> - window.onload = function() { - document.getElementById('login').style.width = '{$width}px'; - document.getElementById('reg_passmail').style.marginTop = '10px'; - document.getElementById('recaptcha_widget_div').style.marginBottom = '10px'; - }; - </script> -REGISTRATION; - } - - function recaptcha_enabled() { - return ($this->options['show_in_comments'] || $this->options['show_in_registration']); - } - - function keys_missing() { - return (empty($this->options['public_key']) || empty($this->options['private_key'])); - } - - function create_error_notice($message, $anchor = '') { - $options_url = admin_url('options-general.php?page=wp-recaptcha/recaptcha.php') . $anchor; - $error_message = sprintf(__($message . ' <a href="%s" title="WP-reCAPTCHA Options">Fix this</a>', 'recaptcha'), $options_url); - - echo '<div class="error"><p><strong>' . $error_message . '</strong></p></div>'; + $this->_require_library(); + + // register the hooks + $this->register_actions(); + $this->register_filters(); + } + + function register_actions() { + // load the plugin's textdomain for localization + add_action('init', array(&$this, 'load_textdomain')); + + // options + register_activation_hook(WPPlugin::path_to_plugin_directory() . + '/wp-recaptcha.php', + array(&$this, 'register_default_options')); + add_action('admin_init', array(&$this, 'register_settings_group')); + + if ($this->is_multi_blog()) { + add_action('signup_extra_fields', array(&$this, + 'show_recaptcha_in_registration')); + } else { + add_action('register_form', array(&$this, + 'show_recaptcha_in_registration')); + } + + add_action('comment_form', array(&$this, 'show_recaptcha_in_comments')); + + // recaptcha comment processing + add_action('wp_head', array(&$this, 'saved_comment'), 0); + add_action('preprocess_comment', array(&$this, 'check_comment'), 0); + add_action('comment_post_redirect', array(&$this, 'relative_redirect'), + 0, 2); + + // administration (menus, pages, notifications, etc.) + add_filter("plugin_action_links", array(&$this, 'show_settings_link'), + 10, 2); + + add_action('admin_menu', array(&$this, 'add_settings_page')); + // admin notices + add_action('admin_notices', array(&$this, 'missing_keys_notice')); + } + + function register_filters() { + if ($this->is_multi_blog()) { + add_filter('wpmu_validate_user_signup', + array(&$this, 'validate_recaptcha_response_wpmu')); + } else { + add_filter('registration_errors', array(&$this, + 'validate_recaptcha_response')); + } + } + + function load_textdomain() { + load_plugin_textdomain('recaptcha', false, 'languages'); + } + + // set the default options + function register_default_options() { + if ($this->options) + return; + $option_defaults = array(); + $old_options = WPPlugin::retrieve_options("recaptcha"); + if ($old_options) { + $option_defaults['site_key'] = $old_options['pubkey']; + $option_defaults['secret'] = $old_options['privkey']; + + // styling + $option_defaults['recaptcha_language'] = $old_options['re_lang']; + + // error handling + $option_defaults['no_response_error'] = $old_options['error_blank']; + } else { + $old_options = WPPlugin::retrieve_options($this->options_name); + if ($old_options) { + $option_defaults['site_key'] = $old_options['public_key']; + $option_defaults['secret'] = $old_options['private_key']; + $option_defaults['comments_theme'] = 'standard'; + $option_defaults['recaptcha_language'] = $old_options['recaptcha_language']; + $option_defaults['no_response_error'] = $old_options['no_response_error']; + } else { + $option_defaults['site_key'] = ''; + $option_defaults['secret'] = ''; + $option_defaults['comments_theme'] = 'standard'; + $option_defaults['recaptcha_language'] = 'en'; + $option_defaults['no_response_error'] = + '<strong>ERROR</strong>: Please fill in the reCAPTCHA form.'; + } } - - function missing_keys_notice() { - if ($this->recaptcha_enabled() && $this->keys_missing()) { - $this->create_error_notice('You enabled reCAPTCHA, but some of the reCAPTCHA API Keys seem to be missing.'); + // add the option based on what environment we're in + WPPlugin::add_options($this->options_name, $option_defaults); + } + + // require the recaptcha library + private function _require_library() { + require_once($this->path_to_plugin_directory() . '/recaptchalib.php'); + } + + // register the settings + function register_settings_group() { + register_setting("recaptcha_options_group", 'recaptcha_options', + array(&$this, 'validate_options')); + } + + function keys_missing() { + return (empty($this->options['site_key']) || + empty($this->options['secret'])); + } + + function create_error_notice($message, $anchor = '') { + $options_url = admin_url( + 'options-general.php?page=wp-recaptcha/recaptcha.php') . $anchor; + $error_message = sprintf(__($message . + ' <a href="%s" title="WP-reCAPTCHA Options">Fix this</a>', + 'recaptcha'), $options_url); + echo '<div class="error"><p><strong>' . $error_message . + '</strong></p></div>'; + } + + function missing_keys_notice() { + if ($this->keys_missing()) { + $this->create_error_notice('reCAPTCHA API Keys are missing.'); + } + } + + function validate_dropdown($array, $key, $value) { + if (in_array($value, $array)) { + return $value; + } else { // if not, load the old value + return $this->options[$key]; + } + } + + function validate_options($input) { + // trim the spaces out of the key + $validated['site_key'] = trim($input['site_key']); + $validated['secret'] = trim($input['secret']); + + $themes = array ('standard', 'light', 'dark'); + $validated['comments_theme'] = $this->validate_dropdown($themes, + 'comments_theme', $input['comments_theme']); + $validated['recaptcha_language'] = $input['recaptcha_language']; + $validated['no_response_error'] = $input['no_response_error']; + return $validated; + } + // display recaptcha + function show_recaptcha_in_registration($errors) { + $escaped_error = htmlentities($_GET['rerror'], ENT_QUOTES); + + // if it's for wordpress mu, show the errors + if ($this->is_multi_blog()) { + $error = $errors->get_error_message('captcha'); + echo '<label for="verification">Verification:</label>'; + echo ($error ? '<p class="error">' . $error . '</p>' : ''); + echo $this->get_recaptcha_html(); + } else { // for regular wordpress + echo $this->get_recaptcha_html(); + } + } + + function validate_recaptcha_response($errors) { + if (empty($_POST['g-recaptcha-response']) || + $_POST['g-recaptcha-response'] == '') { + $errors->add('blank_captcha', $this->options['no_response_error']); + return $errors; + } + + if ($this->_reCaptchaLib == null) { + $this->_reCaptchaLib = new ReCaptcha($this->options['secret']); + } + $response = $this->_reCaptchaLib->verifyResponse( + $_SERVER['REMOTE_ADDR'], + $_POST['g-recaptcha-response']); + + // response is bad, add incorrect response error + if (!$response->success) + $errors->add('captcha_wrong', $response->error); + + return $errors; + } + + function validate_recaptcha_response_wpmu($result) { + if (!$this->is_authority()) { + // blogname in 2.6, blog_id prior to that + // todo: why is this done? + if (isset($_POST['blog_id']) || isset($_POST['blogname'])) + return $result; + // no text entered + if (empty($_POST['g-recaptcha-response']) || + $_POST['g-recaptcha-response'] == '') { + $result['errors']->add('blank_captcha', + $this->options['no_response_error']); + return $result['errors']; } - } - - function validate_dropdown($array, $key, $value) { - // make sure that the capability that was supplied is a valid capability from the drop-down list - if (in_array($value, $array)) - return $value; - else // if not, load the old value - return $this->options[$key]; - } - - function validate_options($input) { - // todo: make sure that 'incorrect_response_error' is not empty, prevent from being empty in the validation phase - - // trim the spaces out of the key, as they are usually present when copied and pasted - // todo: keys seem to usually be 40 characters in length, verify and if confirmed, add to validation process - $validated['public_key'] = trim($input['public_key']); - $validated['private_key'] = trim($input['private_key']); - - $validated['show_in_comments'] = ($input['show_in_comments'] == 1 ? 1 : 0); - $validated['bypass_for_registered_users'] = ($input['bypass_for_registered_users'] == 1 ? 1: 0); - - $capabilities = array ('read', 'edit_posts', 'publish_posts', 'moderate_comments', 'activate_plugins'); - $themes = array ('red', 'white', 'blackglass', 'clean'); - - $recaptcha_languages = array ('en', 'nl', 'fr', 'de', 'pt', 'ru', 'es', 'tr'); - - $validated['minimum_bypass_level'] = $this->validate_dropdown($capabilities, 'minimum_bypass_level', $input['minimum_bypass_level']); - $validated['comments_theme'] = $this->validate_dropdown($themes, 'comments_theme', $input['comments_theme']); - - $validated['comments_tab_index'] = $input['comments_tab_index'] ? $input["comments_tab_index"] : 5; // use the intval filter - - $validated['show_in_registration'] = ($input['show_in_registration'] == 1 ? 1 : 0); - $validated['registration_theme'] = $this->validate_dropdown($themes, 'registration_theme', $input['registration_theme']); - $validated['registration_tab_index'] = $input['registration_tab_index'] ? $input["registration_tab_index"] : 30; // use the intval filter - - $validated['recaptcha_language'] = $this->validate_dropdown($recaptcha_languages, 'recaptcha_language', $input['recaptcha_language']); - $validated['xhtml_compliance'] = ($input['xhtml_compliance'] == 1 ? 1 : 0); - - $validated['no_response_error'] = $input['no_response_error']; - $validated['incorrect_response_error'] = $input['incorrect_response_error']; - - return $validated; - } - - // display recaptcha - function show_recaptcha_in_registration($errors) { - $format = <<<FORMAT - <script type='text/javascript'> - var RecaptchaOptions = { theme : '{$this->options['registration_theme']}', lang : '{$this->options['recaptcha_language']}' , tabindex : {$this->options['registration_tab_index']} }; - </script> -FORMAT; - $comment_string = <<<COMMENT_FORM - <script type='text/javascript'> - document.getElementById('recaptcha_table').style.direction = 'ltr'; - </script> -COMMENT_FORM; - - // todo: is this check necessary? look at the latest recaptchalib.php - if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") - $use_ssl = true; - else - $use_ssl = false; - - $escaped_error = htmlentities($_GET['rerror'], ENT_QUOTES); - - // if it's for wordpress mu, show the errors - if ($this->is_multi_blog()) { - $error = $errors->get_error_message('captcha'); - echo '<label for="verification">Verification:</label>'; - echo ($error ? '<p class="error">'.$error.'</p>' : ''); - echo $format . $this->get_recaptcha_html($escaped_error, $use_ssl); - } - - // for regular wordpress - else { - echo $format . $this->get_recaptcha_html($escaped_error, $use_ssl); - } - } - - function validate_recaptcha_response($errors) { - // empty so throw the empty response error - if (empty($_POST['recaptcha_response_field']) || $_POST['recaptcha_response_field'] == '') { - $errors->add('blank_captcha', $this->options['no_response_error']); - return $errors; + if ($this->_reCaptchaLib == null) { + $this->_reCaptchaLib = new ReCaptcha($this->options['secret']); } - - $response = recaptcha_check_answer($this->options['private_key'], $_SERVER['REMOTE_ADDR'], $_POST['recaptcha_challenge_field'], $_POST['recaptcha_response_field']); + $response = $this->_reCaptchaLib->verifyResponse( + $_SERVER['REMOTE_ADDR'], + $_POST['g-recaptcha-response']); // response is bad, add incorrect response error - if (!$response->is_valid) - if ($response->error == 'incorrect-captcha-sol') - $errors->add('captcha_wrong', $this->options['incorrect_response_error']); - - return $errors; - } - - function validate_recaptcha_response_wpmu($result) { - // must make a check here, otherwise the wp-admin/user-new.php script will keep trying to call - // this function despite not having called do_action('signup_extra_fields'), so the recaptcha - // field was never shown. this way it won't validate if it's called in the admin interface - - if (!$this->is_authority()) { - // blogname in 2.6, blog_id prior to that - // todo: why is this done? - if (isset($_POST['blog_id']) || isset($_POST['blogname'])) - return $result; - - // no text entered - if (empty($_POST['recaptcha_response_field']) || $_POST['recaptcha_response_field'] == '') { - $result['errors']->add('blank_captcha', $this->options['no_response_error']); - return $result; - } - - $response = recaptcha_check_answer($this->options['private_key'], $_SERVER['REMOTEADDR'], $_POST['recaptcha_challenge_field'], $_POST['recaptcha_response_field']); - - // response is bad, add incorrect response error - // todo: why echo the error here? wpmu specific? - if (!$response->is_valid) - if ($response->error == 'incorrect-captcha-sol') { - $result['errors']->add('captcha_wrong', $this->options['incorrect_response_error']); - echo '<div class="error">' . $this->options['incorrect_response_error'] . '</div>'; - } - - return $result; + if (!$response->success) { + $result['errors']->add('captcha_wrong', $response->error); + echo '<div class="error">' . $response->error . '</div>'; } + return $result; } - - // utility methods - function hash_comment($id) { - define ("RECAPTCHA_WP_HASH_SALT", "b7e0638d85f5d7f3694f68e944136d62"); - - if (function_exists('wp_hash')) - return wp_hash(RECAPTCHA_WP_HASH_SALT . $id); - else - return md5(RECAPTCHA_WP_HASH_SALT . $this->options['private_key'] . $id); - } - - function get_recaptcha_html($recaptcha_error, $use_ssl=false) { - return recaptcha_get_html($this->options['public_key'], $recaptcha_error, $use_ssl, $this->options['xhtml_compliance']); - } - - function show_recaptcha_in_comments() { - global $user_ID; - - // set the minimum capability needed to skip the captcha if there is one - if (isset($this->options['bypass_for_registered_users']) && $this->options['bypass_for_registered_users'] && $this->options['minimum_bypass_level']) - $needed_capability = $this->options['minimum_bypass_level']; - - // skip the reCAPTCHA display if the minimum capability is met - if ((isset($needed_capability) && $needed_capability && current_user_can($needed_capability)) || !$this->options['show_in_comments']) - return; - - else { - // Did the user fail to match the CAPTCHA? If so, let them know - if ((isset($_GET['rerror']) && $_GET['rerror'] == 'incorrect-captcha-sol')) - echo '<p class="recaptcha-error">' . $this->options['incorrect_response_error'] . "</p>"; - - //modify the comment form for the reCAPTCHA widget - $recaptcha_js_opts = <<<OPTS - <script type='text/javascript'> - var RecaptchaOptions = { theme : '{$this->options['comments_theme']}', lang : '{$this->options['recaptcha_language']}' , tabindex : {$this->options['comments_tab_index']} }; - </script> -OPTS; - - add_action('wp_footer', array(&$this, 'save_comment_script')); // preserve the comment that was entered - - // todo: replace this with jquery: http://digwp.com/2009/06/including-jquery-in-wordpress-the-right-way/ - // todo: use math to increment+1 the submit button based on what the tab_index option is - if ($this->options['xhtml_compliance']) { - $comment_string = <<<COMMENT_FORM - <div id="recaptcha-submit-btn-area"> </div> + } + // utility methods + function hash_comment($id) { + define ("RECAPTCHA_WP_HASH_SALT", "b7e0638d85f5d7f3694f68e944136d62"); + if (function_exists('wp_hash')) + return wp_hash(RECAPTCHA_WP_HASH_SALT . $id); + else + return md5(RECAPTCHA_WP_HASH_SALT . $this->options['secret'] . $id); + } + + function get_recaptcha_html() { + return '<div class="g-recaptcha" data-sitekey="' . + $this->options['site_key'] . + '" data-theme="' . $this->options['comments_theme'] . + '"></div><script type="text/javascript"' . + 'src="https://www.google.com/recaptcha/api.js?hl=' . + $this->options['recaptcha_language'] . + '"></script>'; + } + + function show_recaptcha_in_comments() { + global $user_ID; + + //modify the comment form for the reCAPTCHA widget + add_action('wp_footer', array(&$this, 'save_comment_script')); + + $comment_string = <<<COMMENT_FORM + <div id="recaptcha-submit-btn-area"> </div> + <noscript> + <style type='text/css'>#submit {display:none;}</style> + <input name="submit" type="submit" id="submit-alt" tabindex="6" + value="Submit Comment"/> + </noscript> COMMENT_FORM; - } - - else { - $comment_string = <<<COMMENT_FORM - <div id="recaptcha-submit-btn-area"> </div> - <noscript> - <style type='text/css'>#submit {display:none;}</style> - <input name="submit" type="submit" id="submit-alt" tabindex="6" value="Submit Comment"/> - </noscript> -COMMENT_FORM; - } - $use_ssl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on"); + $use_ssl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on"); - $escaped_error = htmlentities($_GET['rerror'], ENT_QUOTES); + $escaped_error = htmlentities($_GET['rerror'], ENT_QUOTES); - echo $recaptcha_js_opts . $this->get_recaptcha_html(isset($escaped_error) ? $escaped_error : null, $use_ssl) . $comment_string; - } - } - - // this is what does the submit-button re-ordering - function save_comment_script() { - $javascript = <<<JS - <script type="text/javascript"> - var sub = document.getElementById('submit'); - document.getElementById('recaptcha-submit-btn-area').appendChild (sub); - document.getElementById('submit').tabIndex = 6; - if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') { - document.getElementById('comment').value = _recaptcha_wordpress_savedcomment; - } - document.getElementById('recaptcha_table').style.direction = 'ltr'; - </script> + echo $this->get_recaptcha_html() . $comment_string; + } + + // this is what does the submit-button re-ordering + function save_comment_script() { + $javascript = <<<JS + <script type="text/javascript"> + var sub = document.getElementById('submit'); + document.getElementById('recaptcha-submit-btn-area').appendChild (sub); + document.getElementById('submit').tabIndex = 6; + if ( typeof _recaptcha_wordpress_savedcomment != 'undefined') { + document.getElementById('comment').value = + _recaptcha_wordpress_savedcomment; + } + </script> JS; - echo $javascript; - } - - // todo: this doesn't seem necessary - function show_captcha_for_comment() { - global $user_ID; - return true; - } - - function check_comment($comment_data) { - global $user_ID; - - if ($this->options['bypass_for_registered_users'] && $this->options['minimum_bypass_level']) - $needed_capability = $this->options['minimum_bypass_level']; - - if (($needed_capability && current_user_can($needed_capability)) || !$this->options['show_in_comments']) - return $comment_data; - - if ($this->show_captcha_for_comment()) { - // do not check trackbacks/pingbacks - if ($comment_data['comment_type'] == '') { - $challenge = $_POST['recaptcha_challenge_field']; - $response = $_POST['recaptcha_response_field']; - - $recaptcha_response = recaptcha_check_answer($this->options['private_key'], $_SERVER['REMOTE_ADDR'], $challenge, $response); - - if ($recaptcha_response->is_valid) - return $comment_data; - - else { - $this->saved_error = $recaptcha_response->error; - - // http://codex.wordpress.org/Plugin_API/Filter_Reference#Database_Writes_2 - add_filter('pre_comment_approved', create_function('$a', 'return \'spam\';')); - return $comment_data; - } - } + echo $javascript; + } + + function check_comment($comment_data) { + global $user_ID; + // do not check trackbacks/pingbacks + if ($comment_data['comment_type'] == '') { + if ($this->_reCaptchaLib == null) { + $this->_reCaptchaLib = new ReCaptcha($this->options['secret']); } - - return $comment_data; - } - - function relative_redirect($location, $comment) { - if ($this->saved_error != '') { - // replace #comment- at the end of $location with #commentform - - $location = substr($location, 0, strpos($location, '#')) . - ((strpos($location, "?") === false) ? "?" : "&") . - 'rcommentid=' . $comment->comment_ID . - '&rerror=' . $this->saved_error . - '&rchash=' . $this->hash_comment($comment->comment_ID) . - '#commentform'; + $response = $this->_reCaptchaLib->verifyResponse( + $_SERVER['REMOTE_ADDR'], + $_POST['g-recaptcha-response']); + + if (!$response->success) { + $this->_saved_error = $response->error; + add_filter('pre_comment_approved', + create_function('$a', 'return \'spam\';')); } - - return $location; } - - function saved_comment() { - if (!is_single() && !is_page()) - return; - - $comment_id = $_REQUEST['rcommentid']; - $comment_hash = $_REQUEST['rchash']; - - if (empty($comment_id) || empty($comment_hash)) - return; - - if ($comment_hash == $this->hash_comment($comment_id)) { - $comment = get_comment($comment_id); - - // todo: removed double quote from list of 'dangerous characters' - $com = preg_replace('/([\\/\(\)\+\;\'])/e','\'%\'.dechex(ord(\'$1\'))', $comment->comment_content); - + return $comment_data; + } + + function relative_redirect($location, $comment) { + if ($this->_saved_error != '') { + // replace #comment- at the end of $location with #commentform + $location = substr($location, 0, strpos($location, '#')) . + ((strpos($location, "?") === false) ? "?" : "&") . + 'rcommentid=' . $comment->comment_ID . + '&rerror=' . $this->_saved_error . + '&rchash=' . $this->hash_comment($comment->comment_ID) . + '#commentform'; + } + return $location; + } + + function saved_comment() { + if (!is_single() && !is_page()) + return; + $comment_id = $_REQUEST['rcommentid']; + $comment_hash = $_REQUEST['rchash']; + if (empty($comment_id) || empty($comment_hash)) + return; + if ($comment_hash == $this->hash_comment($comment_id)) { + $comment = get_comment($comment_id); + + // todo: removed double quote from list of 'dangerous characters' + $com = preg_replace('/([\\/\(\)\+\;\'])/e', + '\'%\' . dechex(ord(\'$1\'))', + $comment->comment_content); $com = preg_replace('/\\r\\n/m', '\\\n', $com); - echo " - <script type='text/javascript'> - var _recaptcha_wordpress_savedcomment = '" . $com ."'; - _recaptcha_wordpress_savedcomment = unescape(_recaptcha_wordpress_savedcomment); - </script> - "; - - wp_delete_comment($comment->comment_ID); - } - } - - // todo: is this still needed? - // this is used for the api keys url in the administration interface - function blog_domain() { - $uri = parse_url(get_option('siteurl')); - return $uri['host']; - } - - // add a settings link to the plugin in the plugin list - function show_settings_link($links, $file) { - if ($file == plugin_basename($this->path_to_plugin_directory() . '/wp-recaptcha.php')) { - $settings_title = __('Settings for this Plugin', 'recaptcha'); - $settings = __('Settings', 'recaptcha'); - $settings_link = '<a href="options-general.php?page=wp-recaptcha/recaptcha.php" title="' . $settings_title . '">' . $settings . '</a>'; - array_unshift($links, $settings_link); - } - - return $links; - } - - // add the settings page - function add_settings_page() { - // add the options page - if ($this->environment == Environment::WordPressMU && $this->is_authority()) - add_submenu_page('wpmu-admin.php', 'WP-reCAPTCHA', 'WP-reCAPTCHA', 'manage_options', __FILE__, array(&$this, 'show_settings_page')); - - /* re-add when we figure out a way to add network-wide settings in ms - if ($this->environment == Environment::WordPressMS && $this->is_authority()) - add_submenu_page('ms-admin.php', 'WP-reCAPTCHA', 'WP-reCAPTCHA', 'manage_options', __FILE__, array(&$this, 'show_settings_page')); - */ - - add_options_page('WP-reCAPTCHA', 'WP-reCAPTCHA', 'manage_options', __FILE__, array(&$this, 'show_settings_page')); + <script type='text/javascript'> + var _recaptcha_wordpress_savedcomment = '" . $com ."'; + _recaptcha_wordpress_savedcomment = + unescape(_recaptcha_wordpress_savedcomment); + </script> + "; + + wp_delete_comment($comment->comment_ID); + } + } + + // add a settings link to the plugin in the plugin list + function show_settings_link($links, $file) { + if ($file == plugin_basename($this->path_to_plugin_directory() . + '/wp-recaptcha.php')) { + $settings_title = __('Settings for this Plugin', 'recaptcha'); + $settings = __('Settings', 'recaptcha'); + $settings_link = + '<a href="options-general.php?page=wp-recaptcha/recaptcha.php"' . + ' title="' . $settings_title . '">' . $settings . '</a>'; + array_unshift($links, $settings_link); + } + return $links; + } + + // add the settings page + function add_settings_page() { + // add the options page + if ($this->environment == Environment::WordPressMU && + $this->is_authority()) + add_submenu_page('wpmu-admin.php', 'WP-reCAPTCHA', 'WP-reCAPTCHA', + 'manage_options', __FILE__, array(&$this, 'show_settings_page')); + add_options_page('WP-reCAPTCHA', 'WP-reCAPTCHA', 'manage_options', + __FILE__, array(&$this, 'show_settings_page')); } - // store the xhtml in a separate file and use include on it function show_settings_page() { - include("settings.php"); - } - - function build_dropdown($name, $keyvalue, $checked_value) { - echo '<select name="' . $name . '" id="' . $name . '">' . "\n"; - - foreach ($keyvalue as $key => $value) { - $checked = ($value == $checked_value) ? ' selected="selected" ' : ''; - - echo '\t <option value="' . $value . '"' . $checked . ">$key</option> \n"; - $checked = NULL; - } - - echo "</select> \n"; - } - - function capabilities_dropdown() { - // define choices: Display text => permission slug - $capabilities = array ( - __('all registered users', 'recaptcha') => 'read', - __('edit posts', 'recaptcha') => 'edit_posts', - __('publish posts', 'recaptcha') => 'publish_posts', - __('moderate comments', 'recaptcha') => 'moderate_comments', - __('activate plugins', 'recaptcha') => 'activate_plugins' - ); - - $this->build_dropdown('recaptcha_options[minimum_bypass_level]', $capabilities, $this->options['minimum_bypass_level']); - } - - function theme_dropdown($which) { - $themes = array ( - __('Red', 'recaptcha') => 'red', - __('White', 'recaptcha') => 'white', - __('Black Glass', 'recaptcha') => 'blackglass', - __('Clean', 'recaptcha') => 'clean' - ); - - if ($which == 'comments') - $this->build_dropdown('recaptcha_options[comments_theme]', $themes, $this->options['comments_theme']); - else if ($which == 'registration') - $this->build_dropdown('recaptcha_options[registration_theme]', $themes, $this->options['registration_theme']); - } - - function recaptcha_language_dropdown() { - $languages = array ( - __('English', 'recaptcha') => 'en', - __('Dutch', 'recaptcha') => 'nl', - __('French', 'recaptcha') => 'fr', - __('German', 'recaptcha') => 'de', - __('Portuguese', 'recaptcha') => 'pt', - __('Russian', 'recaptcha') => 'ru', - __('Spanish', 'recaptcha') => 'es', - __('Turkish', 'recaptcha') => 'tr' - ); - - $this->build_dropdown('recaptcha_options[recaptcha_language]', $languages, $this->options['recaptcha_language']); - } - } // end class declaration -} // end of class exists clause + include("settings.php"); + } + + function build_dropdown($name, $keyvalue, $checked_value) { + echo '<select name="' . $name . '" id="' . $name . '">' . "\n"; + foreach ($keyvalue as $key => $value) { + $checked = ($value == $checked_value) ? + ' selected="selected" ' : ''; + echo '\t <option value="' . $value . '"' . $checked . + ">$key</option> \n"; + $checked = NULL; + } + echo "</select> \n"; + } + + function theme_dropdown() { + $themes = array ( + __('Standard', 'recaptcha') => 'standard', + __('Light', 'recaptcha') => 'light', + __('Dark', 'recaptcha') => 'dark' + ); + $this->build_dropdown('recaptcha_options[comments_theme]', $themes, + $this->options['comments_theme']); + } + + function recaptcha_language_dropdown() { + $languages = array ( + __('English', 'recaptcha') => 'en', + __('Arabic', 'recaptcha') => 'ar', + __('Bulgarian', 'recaptcha') => 'bg', + __('Catalan Valencian', 'recaptcha') => 'ca', + __('Czech', 'recaptcha') => 'cs', + __('Danish', 'recaptcha') => 'da', + __('German', 'recaptcha') => 'de', + __('Greek', 'recaptcha') => 'el', + __('British English', 'recaptcha') => 'en_gb', + __('Spanish', 'recaptcha') => 'es', + __('Persian', 'recaptcha') => 'fa', + __('French', 'recaptcha') => 'fr', + __('Canadian French', 'recaptcha') => 'fr_ca', + __('Hindi', 'recaptcha') => 'hi', + __('Croatian', 'recaptcha') => 'hr', + __('Hungarian', 'recaptcha') => 'hu', + __('Indonesian', 'recaptcha') => 'id', + __('Italian', 'recaptcha') => 'it', + __('Hebrew', 'recaptcha') => 'iw', + __('Jananese', 'recaptcha') => 'ja', + __('Korean', 'recaptcha') => 'ko', + __('Lithuanian', 'recaptcha') => 'lt', + __('Latvian', 'recaptcha') => 'lv', + __('Dutch', 'recaptcha') => 'nl', + __('Norwegian', 'recaptcha') => 'no', + __('Polish', 'recaptcha') => 'pl', + __('Portuguese', 'recaptcha') => 'pt', + __('Romanian', 'recaptcha') => 'ro', + __('Russian', 'recaptcha') => 'ru', + __('Slovak', 'recaptcha') => 'sk', + __('Slovene', 'recaptcha') => 'sl', + __('Serbian', 'recaptcha') => 'sr', + __('Swedish', 'recaptcha') => 'sv', + __('Thai', 'recaptcha') => 'th', + __('Turkish', 'recaptcha') => 'tr', + __('Ukrainian', 'recaptcha') => 'uk', + __('Vietnamese', 'recaptcha') => 'vi', + __('Simplified Chinese', 'recaptcha') => 'zh_cn', + __('Traditional Chinese', 'recaptcha') => 'zh_tw' + ); + + $this->build_dropdown('recaptcha_options[recaptcha_language]', + $languages, $this->options['recaptcha_language']); + } +} // end class declaration ?> diff --git a/wp-content/plugins/wp-recaptcha/recaptchalib.php b/wp-content/plugins/wp-recaptcha/recaptchalib.php index 32c4f4d75..a9053e290 100644 --- a/wp-content/plugins/wp-recaptcha/recaptchalib.php +++ b/wp-content/plugins/wp-recaptcha/recaptchalib.php @@ -1,17 +1,15 @@ <?php -/* +/** * This is a PHP library that handles calling reCAPTCHA. * - Documentation and latest version - * http://recaptcha.net/plugins/php/ + * https://developers.google.com/recaptcha/docs/php * - Get a reCAPTCHA API Key * https://www.google.com/recaptcha/admin/create * - Discussion group * http://groups.google.com/group/recaptcha * - * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net - * AUTHORS: - * Mike Crawford - * Ben Maurer + * @copyright Copyright (c) 2014, Google Inc. + * @link http://www.google.com/recaptcha * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,245 +31,110 @@ */ /** - * The reCAPTCHA server URL's - */ -define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api"); -define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api"); -define("RECAPTCHA_VERIFY_SERVER", "www.google.com"); - -/** - * Encodes the given data into a query string format - * @param $data - array of string elements to be encoded - * @return string - encoded request - */ -function _recaptcha_qsencode ($data) { - $req = ""; - foreach ( $data as $key => $value ) - $req .= $key . '=' . urlencode( stripslashes($value) ) . '&'; - - // Cut the last '&' - $req=substr($req,0,strlen($req)-1); - return $req; -} - - - -/** - * Submits an HTTP POST to a reCAPTCHA server - * @param string $host - * @param string $path - * @param array $data - * @param int port - * @return array response + * A ReCaptchaResponse is returned from checkAnswer(). */ -function _recaptcha_http_post($host, $path, $data, $port = 80) { - - $req = _recaptcha_qsencode ($data); - - $http_request = "POST $path HTTP/1.0\r\n"; - $http_request .= "Host: $host\r\n"; - $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; - $http_request .= "Content-Length: " . strlen($req) . "\r\n"; - $http_request .= "User-Agent: reCAPTCHA/PHP\r\n"; - $http_request .= "\r\n"; - $http_request .= $req; - - $response = ''; - if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) { - die ('Could not open socket'); - } - - fwrite($fs, $http_request); - - while ( !feof($fs) ) - $response .= fgets($fs, 1160); // One TCP-IP packet - fclose($fs); - $response = explode("\r\n\r\n", $response, 2); - - return $response; +class ReCaptchaResponse +{ + public $success; + public $errorCodes; } - - -/** - * Gets the challenge HTML (javascript and non-javascript version). - * This is called from the browser, and the resulting reCAPTCHA HTML widget - * is embedded within the HTML form it was called from. - * @param string $pubkey A public key for reCAPTCHA - * @param string $error The error given by reCAPTCHA (optional, default is null) - * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false) - - * @return string - The HTML to be embedded in the user's form. - */ -function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) +class ReCaptcha { - if ($pubkey == null || $pubkey == '') { - die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>"); - } - - if ($use_ssl) { - $server = RECAPTCHA_API_SECURE_SERVER; - } else { - $server = RECAPTCHA_API_SERVER; + private static $_signupUrl = "https://www.google.com/recaptcha/admin"; + private static $_siteVerifyUrl = + "https://www.google.com/recaptcha/api/siteverify?"; + private $_secret; + private static $_version = "wp_php_1.0"; + + /** + * Constructor. + * + * @param string $secret shared secret between site and ReCAPTCHA server. + */ + function ReCaptcha($secret) + { + if ($secret == null || $secret == "") { + die("To use reCAPTCHA you must get an API key from <a href='" + . self::$_signupUrl . "'>" . self::$_signupUrl . "</a>"); } - - $errorpart = ""; - if ($error) { - $errorpart = "&error=" . $error; + $this->_secret=$secret; + } + + /** + * Encodes the given data into a query string format. + * + * @param array $data array of string elements to be encoded. + * + * @return string - encoded request. + */ + private function _encodeQS($data) + { + $req = ""; + foreach ($data as $key => $value) { + $req .= $key . '=' . urlencode(stripslashes($value)) . '&'; } - return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script> - - <noscript> - <iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/> - <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea> - <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/> - </noscript>'; -} - - - - -/** - * A ReCaptchaResponse is returned from recaptcha_check_answer() - */ -class ReCaptchaResponse { - var $is_valid; - var $error; -} - -/** - * Calls an HTTP POST function to verify if the user's guess was correct - * @param string $privkey - * @param string $remoteip - * @param string $challenge - * @param string $response - * @param array $extra_params an array of extra variables to post to the server - * @return ReCaptchaResponse - */ -function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array()) -{ - if ($privkey == null || $privkey == '') { - die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>"); - } - - if ($remoteip == null || $remoteip == '') { - die ("For security reasons, you must pass the remote ip to reCAPTCHA"); - } - - - - //discard spam submissions - if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) { - $recaptcha_response = new ReCaptchaResponse(); - $recaptcha_response->is_valid = false; - $recaptcha_response->error = 'incorrect-captcha-sol'; - return $recaptcha_response; + // Cut the last '&' + $req=substr($req, 0, strlen($req)-1); + return $req; + } + + /** + * Submits an HTTP GET to a reCAPTCHA server. + * + * @param string $path url path to recaptcha server. + * @param array $data array of parameters to be sent. + * + * @return array response + */ + private function _submitHTTPGet($path, $data) + { + $req = $this->_encodeQS($data); + $response = file_get_contents($path . $req); + return $response; + } + + /** + * Calls the reCAPTCHA siteverify API to verify whether the user passes + * CAPTCHA test. + * + * @param string $remoteIp IP address of end user. + * @param string $response response string from recaptcha verification. + * + * @return ReCaptchaResponse + */ + public function verifyResponse($remoteIp, $response) + { + // Discard empty solution submissions + if ($response == null || strlen($response) == 0) { + $recaptchaResponse = new ReCaptchaResponse(); + $recaptchaResponse->success = false; + $recaptchaResponse->errorCodes = 'missing-input'; + return $recaptchaResponse; } - $response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify", - array ( - 'privatekey' => $privkey, - 'remoteip' => $remoteip, - 'challenge' => $challenge, - 'response' => $response - ) + $extra_params - ); - - $answers = explode ("\n", $response [1]); - $recaptcha_response = new ReCaptchaResponse(); - - if (trim ($answers [0]) == 'true') { - $recaptcha_response->is_valid = true; - } - else { - $recaptcha_response->is_valid = false; - $recaptcha_response->error = $answers [1]; + $getResponse = $this->_submitHttpGet( + self::$_siteVerifyUrl, + array ( + 'secret' => $this->_secret, + 'remoteip' => $remoteIp, + 'v' => self::$_version, + 'response' => $response + ) + ); + $answers = json_decode($getResponse, true); + $recaptchaResponse = new ReCaptchaResponse(); + + if (trim($answers [success]) == true) { + $recaptchaResponse->success = true; + } else { + $recaptchaResponse->success = false; + $recaptchaResponse->errorCodes = $answers [error-codes]; } - return $recaptcha_response; - -} - -/** - * gets a URL where the user can sign up for reCAPTCHA. If your application - * has a configuration page where you enter a key, you should provide a link - * using this function. - * @param string $domain The domain where the page is hosted - * @param string $appname The name of your application - */ -function recaptcha_get_signup_url ($domain = null, $appname = null) { - return "https://www.google.com/recaptcha/admin/create?" . _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname)); -} -function _recaptcha_aes_pad($val) { - $block_size = 16; - $numpad = $block_size - (strlen ($val) % $block_size); - return str_pad($val, strlen ($val) + $numpad, chr($numpad)); + return $recaptchaResponse; + } } -/* Mailhide related code */ - -function _recaptcha_aes_encrypt($val,$ky) { - if (! function_exists ("mcrypt_encrypt")) { - die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed."); - } - $mode=MCRYPT_MODE_CBC; - $enc=MCRYPT_RIJNDAEL_128; - $val=_recaptcha_aes_pad($val); - return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); -} - - -function _recaptcha_mailhide_urlbase64 ($x) { - return strtr(base64_encode ($x), '+/', '-_'); -} - -/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */ -function recaptcha_mailhide_url($pubkey, $privkey, $email) { - if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) { - die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " . - "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>"); - } - - - $ky = pack('H*', $privkey); - $cryptmail = _recaptcha_aes_encrypt ($email, $ky); - - return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail); -} - -/** - * gets the parts of the email to expose to the user. - * eg, given johndoe@example,com return ["john", "example.com"]. - * the email is then displayed as john...@example.com - */ -function _recaptcha_mailhide_email_parts ($email) { - $arr = preg_split("/@/", $email ); - - if (strlen ($arr[0]) <= 4) { - $arr[0] = substr ($arr[0], 0, 1); - } else if (strlen ($arr[0]) <= 6) { - $arr[0] = substr ($arr[0], 0, 3); - } else { - $arr[0] = substr ($arr[0], 0, 4); - } - return $arr; -} - -/** - * Gets html to display an email address given a public an private key. - * to get a key, go to: - * - * http://www.google.com/recaptcha/mailhide/apikey - */ -function recaptcha_mailhide_html($pubkey, $privkey, $email) { - $emailparts = _recaptcha_mailhide_email_parts ($email); - $url = recaptcha_mailhide_url ($pubkey, $privkey, $email); - - return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) . - "' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]); - -} - - ?> diff --git a/wp-content/plugins/wp-recaptcha/settings.php b/wp-content/plugins/wp-recaptcha/settings.php index f47bb8e45..fb3606ee6 100644 --- a/wp-content/plugins/wp-recaptcha/settings.php +++ b/wp-content/plugins/wp-recaptcha/settings.php @@ -1,117 +1,65 @@ <?php +/** + * This is a WordPress plugin settings that handles calling reCAPTCHA. + * - Documentation and latest version + * https://developers.google.com/recaptcha/docs/php + * - Get a reCAPTCHA API Key + * https://www.google.com/recaptcha/admin/create + * - Discussion group + * http://groups.google.com/group/recaptcha + * + * @link http://www.google.com/recaptcha + */ - if (defined('ALLOW_INCLUDE') === false) - die('no direct access'); - +if (defined('ALLOW_INCLUDE') === false) + die('no direct access'); ?> <div class="wrap"> <a name="recaptcha"></a> <h2><?php _e('reCAPTCHA Options', 'recaptcha'); ?></h2> - <p><?php _e('reCAPTCHA is a free, accessible CAPTCHA service that helps to digitize books while blocking spam on your blog.', 'recaptcha'); ?></p> - + <p><?php _e('reCAPTCHA is a free, accessible CAPTCHA service that helps to block spam on your blog.', 'recaptcha'); ?></p> + <form method="post" action="options.php"> <?php settings_fields('recaptcha_options_group'); ?> <h3><?php _e('Authentication', 'recaptcha'); ?></h3> - <p><?php _e('These keys are required before you are able to do anything else.', 'recaptcha'); ?> <?php _e('You can get the keys', 'recaptcha'); ?> <a href="<?php echo recaptcha_get_signup_url($this->blog_domain(), 'wordpress');?>" title="<?php _e('Get your reCAPTCHA API Keys', 'recaptcha'); ?>"><?php _e('here', 'recaptcha'); ?></a>.</p> - <p><?php _e('Be sure not to mix them up! The public and private keys are not interchangeable!'); ?></p> - - <table class="form-table"> - <tr valign="top"> - <th scope="row"><?php _e('Public Key', 'recaptcha'); ?></th> - <td> - <input type="text" name="recaptcha_options[public_key]" size="40" value="<?php echo $this->options['public_key']; ?>" /> - </td> - </tr> - <tr valign="top"> - <th scope="row"><?php _e('Private Key', 'recaptcha'); ?></th> - <td> - <input type="text" name="recaptcha_options[private_key]" size="40" value="<?php echo $this->options['private_key']; ?>" /> - </td> - </tr> - </table> - - <h3><?php _e('Comment Options', 'recaptcha'); ?></h3> - <table class="form-table"> - <tr valign="top"> - <th scope="row"><?php _e('Activation', 'recaptcha'); ?></th> - <td> - <input type="checkbox" id ="recaptcha_options[show_in_comments]" name="recaptcha_options[show_in_comments]" value="1" <?php checked('1', $this->options['show_in_comments']); ?> /> - <label for="recaptcha_options[show_in_comments]"><?php _e('Enable for comments form', 'recaptcha'); ?></label> - </td> - </tr> - - <tr valign="top"> - <th scope="row"><?php _e('Target', 'recaptcha'); ?></th> - <td> - <input type="checkbox" id="recaptcha_options[bypass_for_registered_users]" name="recaptcha_options[bypass_for_registered_users]" value="1" <?php checked('1', $this->options['bypass_for_registered_users']); ?> /> - <label for="recaptcha_options[bypass_for_registered_users]"><?php _e('Hide for Registered Users who can', 'recaptcha'); ?></label> - <?php $this->capabilities_dropdown(); ?> - </td> - </tr> + <p><?php _e('These keys are required. You can register them at', 'recaptcha'); ?> + <a href="http://www.google.com/recaptcha/admin/create" title="<?php _e('Get your reCAPTCHA API Keys', 'recaptcha'); ?>"><?php _e('here', 'recaptcha'); ?></a>.</p> + <p><?php _e('These keys should be non-global key!', 'recaptcha'); ?></p> - <tr valign="top"> - <th scope="row"><?php _e('Presentation', 'recaptcha'); ?></th> - <td> - <label for="recaptcha_options[comments_theme]"><?php _e('Theme:', 'recaptcha'); ?></label> - <?php $this->theme_dropdown('comments'); ?> - </td> - </tr> - - <tr valign="top"> - <th scope="row"><?php _e('Tab Index', 'recaptcha'); ?></th> - <td> - <input type="text" name="recaptcha_options[comments_tab_index]" size="10" value="<?php echo $this->options['comments_tab_index']; ?>" /> - </td> - </tr> - </table> - - <h3><?php _e('Registration Options', 'recaptcha'); ?></h3> <table class="form-table"> <tr valign="top"> - <th scope="row"><?php _e('Activation', 'recaptcha'); ?></th> - <td> - <input type="checkbox" id ="recaptcha_options[show_in_registration]" name="recaptcha_options[show_in_registration]" value="1" <?php checked('1', $this->options['show_in_registration']); ?> /> - <label for="recaptcha_options[show_in_registration]"><?php _e('Enable for registration form', 'recaptcha'); ?></label> - </td> - </tr> - - <tr valign="top"> - <th scope="row"><?php _e('Presentation', 'recaptcha'); ?></th> + <th scope="row"><?php _e('Site Key (Public Key)', 'recaptcha'); ?></th> <td> - <label for="recaptcha_options[registration_theme]"><?php _e('Theme:', 'recaptcha'); ?></label> - <?php $this->theme_dropdown('registration'); ?> + <input type="text" name="recaptcha_options[site_key]" size="40" value="<?php echo $this->options['site_key']; ?>" /> </td> </tr> - <tr valign="top"> - <th scope="row"><?php _e('Tab Index', 'recaptcha'); ?></th> + <th scope="row"><?php _e('Secret (Private Key)', 'recaptcha'); ?></th> <td> - <input type="text" name="recaptcha_options[registration_tab_index]" size="10" value="<?php echo $this->options['registration_tab_index']; ?>" /> + <input type="text" name="recaptcha_options[secret]" size="40" value="<?php echo $this->options['secret']; ?>" /> </td> </tr> </table> - + <h3><?php _e('General Options', 'recaptcha'); ?></h3> <table class="form-table"> <tr valign="top"> - <th scope="row"><?php _e('reCAPTCHA Form', 'recaptcha'); ?></th> + <th scope="row"><?php _e('Theme', 'recaptcha'); ?></th> <td> - <label for="recaptcha_options[recaptcha_language]"><?php _e('Language:', 'recaptcha'); ?></label> - <?php $this->recaptcha_language_dropdown(); ?> + <?php $this->theme_dropdown(); ?> </td> </tr> - + <tr valign="top"> - <th scope="row"><?php _e('Standards Compliance', 'recaptcha'); ?></th> + <th scope="row"><?php _e('Language', 'recaptcha'); ?></th> <td> - <input type="checkbox" id ="recaptcha_options[xhtml_compliance]" name="recaptcha_options[xhtml_compliance]" value="1" <?php checked('1', $this->options['xhtml_compliance']); ?> /> - <label for="recaptcha_options[xhtml_compliance]"><?php _e('Produce XHTML 1.0 Strict Compliant Code', 'recaptcha'); ?></label> + <?php $this->recaptcha_language_dropdown(); ?> </td> </tr> </table> - + <h3><?php _e('Error Messages', 'recaptcha'); ?></h3> <table class="form-table"> <tr valign="top"> @@ -120,17 +68,10 @@ <input type="text" name="recaptcha_options[no_response_error]" size="70" value="<?php echo $this->options['no_response_error']; ?>" /> </td> </tr> - - <tr valign="top"> - <th scope="row"><?php _e('Incorrect Guess', 'recaptcha'); ?></th> - <td> - <input type="text" name="recaptcha_options[incorrect_response_error]" size="70" value="<?php echo $this->options['incorrect_response_error']; ?>" /> - </td> - </tr> </table> <p class="submit"><input type="submit" class="button-primary" title="<?php _e('Save reCAPTCHA Options') ?>" value="<?php _e('Save reCAPTCHA Changes') ?> »" /></p> </form> - + <?php do_settings_sections('recaptcha_options_page'); ?> </div> \ No newline at end of file diff --git a/wp-content/plugins/wp-recaptcha/uninstall.php b/wp-content/plugins/wp-recaptcha/uninstall.php index b13fc0289..3e23a59d4 100644 --- a/wp-content/plugins/wp-recaptcha/uninstall.php +++ b/wp-content/plugins/wp-recaptcha/uninstall.php @@ -12,7 +12,4 @@ function uninstall_options($name) { // recaptcha uninstall_options('recaptcha_options'); -// mailhide -uninstall_options('mailhide_options'); - ?> \ No newline at end of file diff --git a/wp-content/plugins/wp-recaptcha/wp-plugin.php b/wp-content/plugins/wp-recaptcha/wp-plugin.php index 44a88ef16..ef05111ee 100644 --- a/wp-content/plugins/wp-recaptcha/wp-plugin.php +++ b/wp-content/plugins/wp-recaptcha/wp-plugin.php @@ -3,7 +3,6 @@ // just making sure the constant is defined if (!defined('WP_CONTENT_DIR')) define('WP_CONTENT_DIR', ABSPATH . 'wp-content'); - if (!class_exists('Environment')) { class Environment { @@ -16,40 +15,40 @@ if (!class_exists('Environment')) { if (!class_exists('WPPlugin')) { abstract class WPPlugin { protected $environment; // what environment are we in - protected $options_name; // the name of the options associated with this plugin - + protected $options_name; // the name of the options + protected $options; - + function WPPlugin($options_name) { $args = func_get_args(); call_user_func_array(array(&$this, "__construct"), $args); } - + function __construct($options_name) { $this->environment = WPPlugin::determine_environment(); $this->options_name = $options_name; - + $this->options = WPPlugin::retrieve_options($this->options_name); } - + // sub-classes determine what actions and filters to hook abstract protected function register_actions(); abstract protected function register_filters(); - + // environment checking static function determine_environment() { global $wpmu_version; - + if (function_exists('is_multisite')) if (is_multisite()) return Environment::WordPressMS; - + if (!empty($wpmu_version)) return Environment::WordPressMU; - + return Environment::WordPress; } - + // path finding static function plugins_directory() { if (WPPlugin::determine_environment() == Environment::WordPressMU) @@ -57,38 +56,38 @@ if (!class_exists('WPPlugin')) { else return WP_CONTENT_DIR . '/plugins'; } - + static function plugins_url() { if (WPPlugin::determine_environment() == Environment::WordPressMU) return site_url() . '/wp-content/mu-plugins'; else return site_url() . '/wp-content/plugins'; } - + static function path_to_plugin_directory() { $current_directory = basename(dirname(__FILE__)); - + return WPPlugin::plugins_directory() . "/${current_directory}"; } - + static function url_to_plugin_directory() { $current_directory = basename(dirname(__FILE__)); - + return WPPlugin::plugins_url() . "/${current_directory}"; } - + static function path_to_plugin($file_path) { $file_name = basename($file_path); // /etc/blah/file.txt => file.txt - + if (WPPlugin::determine_environment() == Environment::WordPressMU) return WPPlugin::plugins_directory() . "/${file_name}"; else return WPPlugin::path_to_plugin_directory() . "/${file_name}"; } - + // options abstract protected function register_default_options(); - + // option retrieval static function retrieve_options($options_name) { if (WPPlugin::determine_environment() == Environment::WordPressMU) @@ -96,33 +95,33 @@ if (!class_exists('WPPlugin')) { else return get_option($options_name); } - + static function remove_options($options_name) { if (WPPlugin::determine_environment() == Environment::WordPressMU) return delete_site_option($options_name); else return delete_option($options_name); } - + static function add_options($options_name, $options) { if (WPPlugin::determine_environment() == Environment::WordPressMU) return add_site_option($options_name, $options); else return add_option($options_name, $options); } - + protected function is_multi_blog() { return $this->environment != Environment::WordPress; } - - // calls the appropriate 'authority' checking function depending on the environment + + // calls the appropriate 'authority' checking function protected function is_authority() { if ($this->environment == Environment::WordPress) return is_admin(); - + if ($this->environment == Environment::WordPressMU) return is_site_admin(); - + if ($this->environment == Environment::WordPressMS) return is_super_admin(); } diff --git a/wp-content/plugins/wp-recaptcha/wp-recaptcha.php b/wp-content/plugins/wp-recaptcha/wp-recaptcha.php index a4c2b47f4..8810ee1ce 100644 --- a/wp-content/plugins/wp-recaptcha/wp-recaptcha.php +++ b/wp-content/plugins/wp-recaptcha/wp-recaptcha.php @@ -1,12 +1,9 @@ <?php /* Plugin Name: WP-reCAPTCHA -Plugin URI: https://github.com/blaenk/wp-recaptcha Description: Integrates reCAPTCHA anti-spam solutions with wordpress -Version: 3.2 -Author: Jorge Peña +Version: 4.1 Email: support@recaptcha.net -Author URI: https://github.com/blaenk */ // this is the 'driver' file that instantiates the objects and registers every hook @@ -14,9 +11,7 @@ Author URI: https://github.com/blaenk define('ALLOW_INCLUDE', true); require_once('recaptcha.php'); -require_once('mailhide.php'); -$recaptcha = new reCAPTCHA('recaptcha_options'); -$mailhide = new MailHide('mailhide_options'); +$recaptcha = new ReCAPTCHAPlugin('recaptcha_options'); ?> -- GitLab