PageRenderTime 27ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/mu-plugins/math-comment-spam-protection.php

https://github.com/socialplanning/opencore-wordpress-mu
PHP | 347 lines | 188 code | 69 blank | 90 comment | 12 complexity | 264579b45d99ccd2b7102dac11062748 MD5 | raw file
  1. <?php
  2. /*
  3. Plugin Name: Math Comment Spam Protection
  4. Plugin URI: http://sw-guide.de/wordpress/comment-spam-protection-plugin/
  5. Description: Asks the visitor making the comment to answer a simple math question. This is intended to prove that the visitor is a human being and not a spam robot. Example of such question: <em>What is the sum of 2 and 9</em>?
  6. Version: 2.0
  7. Author: Michael Woehrer
  8. Author URI: http://sw-guide.de/
  9. */
  10. /* ----------------------------------------------------------------------------
  11. ____________________________________________________
  12. | |
  13. | Math Comment Spam Protection |
  14. | © Michael Woehrer |
  15. |____________________________________________________|
  16. © Copyright 2006 Michael Woehrer (michael dot woehrer at gmail dot com)
  17. This program is free software; you can redistribute it and/or modify
  18. it under the terms of the GNU General Public License as published by
  19. the Free Software Foundation; either version 2 of the License, or
  20. (at your option) any later version.
  21. This program is distributed in the hope that it will be useful,
  22. but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. GNU General Public License for more details.
  25. ----------------------------------------------------------------------------
  26. ACKNOWLEDGEMENTS:
  27. - Thanks to Steven Herod (http://www.herod.net/) for his plugin
  28. "Did You Pass Math?". I took his idea and extended/improved it by
  29. writing a plugin on my own.
  30. ----------------------------------------------------------------------------
  31. INSTALLATION, USAGE:
  32. Visit the plugin's homepage.
  33. ----------------------------------------------------------------------------
  34. */
  35. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  36. Get settings
  37. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  38. $mcsp_opt = get_option('plugin_mathcommentspamprotection');
  39. /*******************************************************************************
  40. * Generate math question
  41. ******************************************************************************/
  42. function math_comment_spam_protection() {
  43. global $mcsp_opt;
  44. // Get numbers in array
  45. $num_array = mcsp_aux_numbers_to_array($mcsp_opt['mcsp_opt_numbers']);
  46. // Get random keys
  47. $rand_keys = array_rand($num_array, 2);
  48. // Operands for displaying...
  49. $mcsp_info['operand1'] = $num_array[$rand_keys[0]];
  50. $mcsp_info['operand2'] = $num_array[$rand_keys[1]];
  51. // Calculate result
  52. $result = $rand_keys[0] + $rand_keys[1];
  53. $mcsp_info['result'] = mcsp_aux_generate_hash($result, date(j));
  54. return $mcsp_info;
  55. }
  56. /*******************************************************************************
  57. * Input validation. We use the special function to generate an encryption value
  58. * since we want to avoid the usage of cookies.
  59. ******************************************************************************/
  60. function mcsp_check_input($comment_data) {
  61. global $user_ID, $mcsp_opt;
  62. if ( !isset($user_ID) ) { // Do not check if the user is registered.
  63. if ( $comment_data['comment_type'] == '' ) { // Do not check trackbacks/pingbacks
  64. // Get result
  65. $value_result = $_POST[ $mcsp_opt['mcsp_opt_fieldname_mathresult'] ];
  66. // Get value user has entered
  67. $value_entered = $_POST[ $mcsp_opt['mcsp_opt_fieldname_useranswer'] ];
  68. $value_entered = preg_replace('/[^0-9]/','',$value_entered); // Remove everything except numbers
  69. if ($value_entered == '') {
  70. // Case 1: User has not entered an answer at all:
  71. die( __(stripslashes($mcsp_opt['mcsp_opt_msg_no_answer'])) );
  72. } elseif ( $value_result != mcsp_aux_generate_hash($value_entered, date(j)) ) {
  73. if ( ( date('G') <= 1 ) AND ( $value_result == mcsp_aux_generate_hash($value_entered, (intval(date(j))-1) ) ) ) {
  74. // User has just passed midnight while writing the comment. We consider
  75. // the time between 0:00 and 1:59 still as the day before to avoid
  76. // error messages if user visited page on 23:50 but pressed the "Submit Comment"
  77. // button on 0:15.
  78. } else {
  79. // Case 2: User has entered a wrong answer:
  80. die( __(stripslashes($mcsp_opt['mcsp_opt_msg_wrong_answer'])) );
  81. }
  82. }
  83. }
  84. }
  85. return $comment_data;
  86. }
  87. /*******************************************************************************
  88. * Generate hash
  89. ******************************************************************************/
  90. function mcsp_aux_generate_hash($inputstring, $day) {
  91. // Add IP address:
  92. // [ not use for now... if users using dial-up connections, disconnect when writing
  93. // the comment and re-connect again, they will get a new IP address. ]
  94. // $inputstring .= getenv('REMOTE_ADDR');
  95. // Add name of the weblog:
  96. $inputstring .= get_bloginfo('name');
  97. // Add date:
  98. $inputstring .= $day . date('ny');
  99. // Get MD5 and reverse it
  100. $enc = strrev(md5($inputstring));
  101. // Get only a few chars out of the string
  102. $enc = substr($enc, 26, 1) . substr($enc, 10, 1) . substr($enc, 23, 1) . substr($enc, 3, 1) . substr($enc, 19, 1);
  103. // Return result
  104. return $enc;
  105. }
  106. /*******************************************************************************
  107. * Apply plugin
  108. ******************************************************************************/
  109. add_filter('preprocess_comment', 'mcsp_check_input', 0);
  110. ##################################################################################################################################
  111. /*******************************************************************************
  112. * Admin
  113. *******************************************************************************/
  114. // Add admin menu
  115. function mcsp_add_options_to_admin() {
  116. if (function_exists('add_options_page')) {
  117. add_options_page('Math Comment Spam', 'Math Comment Spam', 8, basename(__FILE__), 'mcsp_options_subpanel');
  118. }
  119. }
  120. // This will add the new item, 'Math Comment Spam', to the Options menu.
  121. function mcsp_options_subpanel() {
  122. /* Lets add some default options if they don't exist
  123. If an option with the specified name already exists, no changes are made to its value
  124. or to the database as a whole. add_option() can only add options, not alter them.*/
  125. $tmp_noanswer = '<p align="center">
  126. <strong>Error:</strong> Please press the back button and fill the required field for spam protection.
  127. </p>';
  128. $tmp_wronganswer = '<p align="center">
  129. <strong>Error:</strong> You have entered the wrong sum in the spam protection field.
  130. <br />Press the back button and try again.
  131. </p>';
  132. $optionarray_def = array(
  133. 'mcsp_opt_numbers' => '1~1, 2~2, 3~3, 4~4, 5~5, 6~6, 7~7, 8~8, 9~9, 10~10',
  134. 'mcsp_opt_msg_no_answer' => $tmp_noanswer,
  135. 'mcsp_opt_msg_wrong_answer' => $tmp_wronganswer,
  136. 'mcsp_opt_fieldname_useranswer' => 'mcspvalue',
  137. 'mcsp_opt_fieldname_mathresult' => 'mcspinfo',
  138. );
  139. add_option('plugin_mathcommentspamprotection', $optionarray_def, 'Math Comment Spam Protection Plugin Options');
  140. /* Check form submission and update options if no error occurred */
  141. if (isset($_POST['submit']) ) {
  142. $optionarray_update = array (
  143. 'mcsp_opt_numbers' => mcsp_aux_numbers_input_formatting($_POST['mcsp_opt_numbers']),
  144. 'mcsp_opt_msg_no_answer' => $_POST['mcsp_opt_msg_no_answer'],
  145. 'mcsp_opt_msg_wrong_answer' => $_POST['mcsp_opt_msg_wrong_answer'],
  146. 'mcsp_opt_fieldname_useranswer' => mcsp_aux_fieldname_formatting($_POST['mcsp_opt_fieldname_useranswer']),
  147. 'mcsp_opt_fieldname_mathresult' => mcsp_aux_fieldname_formatting($_POST['mcsp_opt_fieldname_mathresult'])
  148. );
  149. update_option('plugin_mathcommentspamprotection', $optionarray_update);
  150. }
  151. /* Get options */
  152. $optionarray_def = get_option('plugin_mathcommentspamprotection');
  153. ?>
  154. <!-- ############################## BEGIN: ADMIN OPTIONS ################### -->
  155. <div class="wrap">
  156. <h2>Math Comment Spam Protection Options</h2>
  157. <p>For details, visit the <a title="Math Comment Spam Protection Plugin" href="http://sw-guide.de/wordpress/math-comment-spam-protection-plugin/">plugin's homepage</a>.
  158. <form name="form1" method="post" action="<?php echo $_SERVER['PHP_SELF'] . '?page=' . basename(__FILE__); ?>&updated=true">
  159. <!-- ****************** Operands ****************** -->
  160. <fieldset class="options">
  161. <legend>Used Operands</legend>
  162. <p style="margin-left: 25px; color: #555; font-size: .85em;">
  163. Enter the numbers to be used. Use the number on the left side, tilde (~) as separator and then the term to display.
  164. Separate values with comma (,).
  165. <br />Examples:
  166. <br />&nbsp;-&nbsp;<em>1~one, 2~two, 3~three, 4~four, 5~five, 6~six, 7~seven, 8~eight, 9~nine, 10~ten</em>
  167. <br />&nbsp;-&nbsp;<em>1~1, 2~2, 3~3, 4~4, 5~5, 6~6, 7~7, 8~8, 9~9, 10~10</em>
  168. </p>
  169. <textarea style="margin-left: 25px" name="mcsp_opt_numbers" id="mcsp_opt_numbers" cols="100%" rows="2"><?php
  170. echo htmlspecialchars(stripslashes(mcsp_aux_numbers_input_formatting($optionarray_def['mcsp_opt_numbers'])));
  171. ?></textarea>
  172. </fieldset>
  173. <!-- ****************** Field Names ****************** -->
  174. <fieldset class="options">
  175. <legend>Field Names</legend>
  176. <p style="margin-left: 25px; color: #555; font-size: .85em;">
  177. <label for="mcsp_opt_fieldname_useranswer">Name of field for user's answer:</label>
  178. <br /><input name="mcsp_opt_fieldname_useranswer" type="text" id="mcsp_opt_fieldname_useranswer" value="<?php echo $optionarray_def['mcsp_opt_fieldname_useranswer']; ?>" size="30" />
  179. <br />
  180. <label for="mcsp_opt_fieldname_mathresult">Name of hidden field that contains the hash:</label>
  181. <br /><input name="mcsp_opt_fieldname_mathresult" type="text" id="mcsp_opt_fieldname_mathresult" value="<?php echo $optionarray_def['mcsp_opt_fieldname_mathresult']; ?>" size="30" />
  182. </p>
  183. </fieldset>
  184. <!-- ****************** Error Messages ****************** -->
  185. <fieldset class="options">
  186. <legend>Error Messages</legend>
  187. <!-- No Answer -->
  188. <p style="margin-left: 25px; color: #555; font-size: .85em;">
  189. Error message being displayed in case of no answer (empty field) / not entered a number:
  190. </p>
  191. <textarea style="margin-left: 25px" name="mcsp_opt_msg_no_answer" id="mcsp_opt_msg_no_answer" cols="100%" rows="3"><?php
  192. echo htmlspecialchars(stripslashes($optionarray_def['mcsp_opt_msg_no_answer']));
  193. ?></textarea>
  194. <!-- Wrong Answer -->
  195. <p style="margin-left: 25px; color: #555; font-size: .85em;">
  196. Error message being displayed in case of a wrong answer:
  197. </p>
  198. <textarea style="margin-left: 25px" name="mcsp_opt_msg_wrong_answer" id="mcsp_opt_msg_wrong_answer" cols="100%" rows="3"><?php
  199. echo htmlspecialchars(stripslashes($optionarray_def['mcsp_opt_msg_wrong_answer']));
  200. ?></textarea>
  201. </fieldset>
  202. <div class="submit">
  203. <input type="submit" name="submit" value="<?php _e('Update Options') ?> &raquo;" />
  204. </div>
  205. </form>
  206. <p style="text-align: center; font-size: .85em;">&copy; Copyright 2006&nbsp;&nbsp;<a href="http://sw-guide.de">Michael W&ouml;hrer</a></p>
  207. </div> <!-- [wrap] -->
  208. <!-- ############################## END: ADMIN OPTIONS ##################### -->
  209. <?php
  210. } // function mcsp_options_subpanel
  211. function mcsp_aux_numbers_input_formatting($input) {
  212. // Formats the input of the numbers...
  213. $result = str_replace(' ', '', $input); // Strip whitespace
  214. $result = preg_replace('/,/', ', ', $result); // Add whitespace after comma
  215. $result = preg_replace('/(\r\n|\n|\r)/', '', $result); // Strip line breaks
  216. return $result;
  217. }
  218. function mcsp_aux_numbers_to_array($input) {
  219. // Converts the input string, e.g. "1~one, 2~two, 3~three, 4~four, ..."
  220. // into an array, e.g.: Array([1] => one, [2] => two, [3] => three, ...)
  221. $input = str_replace(' ', '', $input); // Strip whitespace
  222. $sourcearray = explode(',', $input); // Create array
  223. foreach ($sourcearray as $loopval) {
  224. $temparr = explode('~', $loopval);
  225. $targetarray[$temparr[0]] = $temparr[1];
  226. }
  227. return $targetarray;
  228. }
  229. function mcsp_aux_fieldname_formatting($input) {
  230. // Clean the input values for the field names...
  231. $return = preg_replace('/[^a-zA-Z0-9_\-]/', '', $input);
  232. return $return;
  233. }
  234. /* =============================================================================
  235. Apply the admin menu
  236. ============================================================================= */
  237. add_action('admin_menu', 'mcsp_add_options_to_admin');
  238. ?>