PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/plugin/contact-form-7/modules/captcha.php

https://github.com/core2062/CORE-Website
PHP | 509 lines | 366 code | 133 blank | 10 comment | 77 complexity | 8fe15557244e7eea1139094a752a412c MD5 | raw file
Possible License(s): GPL-3.0, AGPL-1.0, GPL-2.0
  1. <?php
  2. /**
  3. ** A base module for [captchac] and [captchar]
  4. **/
  5. /* Shortcode handler */
  6. add_action( 'init', 'wpcf7_add_shortcode_captcha', 5 );
  7. function wpcf7_add_shortcode_captcha() {
  8. wpcf7_add_shortcode( array( 'captchac', 'captchar' ),
  9. 'wpcf7_captcha_shortcode_handler', true );
  10. }
  11. function wpcf7_captcha_shortcode_handler( $tag ) {
  12. $tag = new WPCF7_Shortcode( $tag );
  13. if ( 'captchac' == $tag->type && ! class_exists( 'ReallySimpleCaptcha' ) )
  14. return '<em>' . __( 'To use CAPTCHA, you need <a href="http://wordpress.org/extend/plugins/really-simple-captcha/">Really Simple CAPTCHA</a> plugin installed.', 'wpcf7' ) . '</em>';
  15. if ( empty( $tag->name ) )
  16. return '';
  17. $validation_error = wpcf7_get_validation_error( $tag->name );
  18. $class = wpcf7_form_controls_class( $tag->type );
  19. if ( 'captchac' == $tag->type ) { // CAPTCHA-Challenge (image)
  20. $class .= ' wpcf7-captcha-' . $tag->name;
  21. $atts = array();
  22. $atts['class'] = $tag->get_class_option( $class );
  23. $atts['id'] = $tag->get_option( 'id', 'id', true );
  24. $op = array( // Default
  25. 'img_size' => array( 72, 24 ),
  26. 'base' => array( 6, 18 ),
  27. 'font_size' => 14,
  28. 'font_char_width' => 15 );
  29. $op = array_merge( $op, wpcf7_captchac_options( $tag->options ) );
  30. if ( ! $filename = wpcf7_generate_captcha( $op ) )
  31. return '';
  32. if ( ! empty( $op['img_size'] ) ) {
  33. if ( isset( $op['img_size'][0] ) )
  34. $atts['width'] = $op['img_size'][0];
  35. if ( isset( $op['img_size'][1] ) )
  36. $atts['height'] = $op['img_size'][1];
  37. }
  38. $atts['alt'] = 'captcha';
  39. $atts['src'] = trailingslashit( wpcf7_captcha_tmp_url() ) . $filename;
  40. $atts = wpcf7_format_atts( $atts );
  41. $prefix = substr( $filename, 0, strrpos( $filename, '.' ) );
  42. $html = sprintf(
  43. '<input type="hidden" name="_wpcf7_captcha_challenge_%1$s" value="%2$s" /><img %3$s />',
  44. $tag->name, $prefix, $atts );
  45. return $html;
  46. } elseif ( 'captchar' == $tag->type ) { // CAPTCHA-Response (input)
  47. if ( $validation_error )
  48. $class .= ' wpcf7-not-valid';
  49. $atts = array();
  50. $atts['size'] = $tag->get_size_option( '40' );
  51. $atts['maxlength'] = $tag->get_maxlength_option();
  52. $atts['class'] = $tag->get_class_option( $class );
  53. $atts['id'] = $tag->get_option( 'id', 'id', true );
  54. $atts['tabindex'] = $tag->get_option( 'tabindex', 'int', true );
  55. $value = (string) reset( $tag->values );
  56. if ( wpcf7_is_posted() )
  57. $value = '';
  58. if ( $tag->has_option( 'placeholder' ) || $tag->has_option( 'watermark' ) ) {
  59. $atts['placeholder'] = $value;
  60. $value = '';
  61. }
  62. $atts['value'] = $value;
  63. $atts['type'] = 'text';
  64. $atts['name'] = $tag->name;
  65. $atts = wpcf7_format_atts( $atts );
  66. $html = sprintf(
  67. '<span class="wpcf7-form-control-wrap %1$s"><input %2$s />%3$s</span>',
  68. $tag->name, $atts, $validation_error );
  69. return $html;
  70. }
  71. }
  72. /* Validation filter */
  73. add_filter( 'wpcf7_validate_captchar', 'wpcf7_captcha_validation_filter', 10, 2 );
  74. function wpcf7_captcha_validation_filter( $result, $tag ) {
  75. $tag = new WPCF7_Shortcode( $tag );
  76. $type = $tag->type;
  77. $name = $tag->name;
  78. $captchac = '_wpcf7_captcha_challenge_' . $name;
  79. $prefix = isset( $_POST[$captchac] ) ? (string) $_POST[$captchac] : '';
  80. $response = isset( $_POST[$name] ) ? (string) $_POST[$name] : '';
  81. if ( $prefix ) {
  82. if ( ! wpcf7_check_captcha( $prefix, $response ) ) {
  83. $result['valid'] = false;
  84. $result['reason'][$name] = wpcf7_get_message( 'captcha_not_match' );
  85. }
  86. wpcf7_remove_captcha( $prefix );
  87. }
  88. return $result;
  89. }
  90. /* Ajax echo filter */
  91. add_filter( 'wpcf7_ajax_onload', 'wpcf7_captcha_ajax_refill' );
  92. add_filter( 'wpcf7_ajax_json_echo', 'wpcf7_captcha_ajax_refill' );
  93. function wpcf7_captcha_ajax_refill( $items ) {
  94. if ( ! is_array( $items ) )
  95. return $items;
  96. $fes = wpcf7_scan_shortcode( array( 'type' => 'captchac' ) );
  97. if ( empty( $fes ) )
  98. return $items;
  99. $refill = array();
  100. foreach ( $fes as $fe ) {
  101. $name = $fe['name'];
  102. $options = $fe['options'];
  103. if ( empty( $name ) )
  104. continue;
  105. $op = wpcf7_captchac_options( $options );
  106. if ( $filename = wpcf7_generate_captcha( $op ) ) {
  107. $captcha_url = trailingslashit( wpcf7_captcha_tmp_url() ) . $filename;
  108. $refill[$name] = $captcha_url;
  109. }
  110. }
  111. if ( ! empty( $refill ) )
  112. $items['captcha'] = $refill;
  113. return $items;
  114. }
  115. /* Messages */
  116. add_filter( 'wpcf7_messages', 'wpcf7_captcha_messages' );
  117. function wpcf7_captcha_messages( $messages ) {
  118. return array_merge( $messages, array( 'captcha_not_match' => array(
  119. 'description' => __( "The code that sender entered does not match the CAPTCHA", 'wpcf7' ),
  120. 'default' => __( 'Your entered code is incorrect.', 'wpcf7' )
  121. ) ) );
  122. }
  123. /* Tag generator */
  124. add_action( 'admin_init', 'wpcf7_add_tag_generator_captcha', 45 );
  125. function wpcf7_add_tag_generator_captcha() {
  126. if ( ! function_exists( 'wpcf7_add_tag_generator' ) )
  127. return;
  128. wpcf7_add_tag_generator( 'captcha', __( 'CAPTCHA', 'wpcf7' ),
  129. 'wpcf7-tg-pane-captcha', 'wpcf7_tg_pane_captcha' );
  130. }
  131. function wpcf7_tg_pane_captcha( &$contact_form ) {
  132. ?>
  133. <div id="wpcf7-tg-pane-captcha" class="hidden">
  134. <form action="">
  135. <table>
  136. <?php if ( ! class_exists( 'ReallySimpleCaptcha' ) ) : ?>
  137. <tr><td colspan="2"><strong style="color: #e6255b"><?php echo esc_html( __( "Note: To use CAPTCHA, you need Really Simple CAPTCHA plugin installed.", 'wpcf7' ) ); ?></strong><br /><a href="http://wordpress.org/extend/plugins/really-simple-captcha/">http://wordpress.org/extend/plugins/really-simple-captcha/</a></td></tr>
  138. <?php endif; ?>
  139. <tr><td><?php echo esc_html( __( 'Name', 'wpcf7' ) ); ?><br /><input type="text" name="name" class="tg-name oneline" /></td><td></td></tr>
  140. </table>
  141. <table class="scope captchac">
  142. <caption><?php echo esc_html( __( "Image settings", 'wpcf7' ) ); ?></caption>
  143. <tr>
  144. <td><code>id</code> (<?php echo esc_html( __( 'optional', 'wpcf7' ) ); ?>)<br />
  145. <input type="text" name="id" class="idvalue oneline option" /></td>
  146. <td><code>class</code> (<?php echo esc_html( __( 'optional', 'wpcf7' ) ); ?>)<br />
  147. <input type="text" name="class" class="classvalue oneline option" /></td>
  148. </tr>
  149. <tr>
  150. <td><?php echo esc_html( __( "Foreground color", 'wpcf7' ) ); ?> (<?php echo esc_html( __( 'optional', 'wpcf7' ) ); ?>)<br />
  151. <input type="text" name="fg" class="color oneline option" /></td>
  152. <td><?php echo esc_html( __( "Background color", 'wpcf7' ) ); ?> (<?php echo esc_html( __( 'optional', 'wpcf7' ) ); ?>)<br />
  153. <input type="text" name="bg" class="color oneline option" /></td>
  154. </tr>
  155. <tr><td colspan="2"><?php echo esc_html( __( "Image size", 'wpcf7' ) ); ?> (<?php echo esc_html( __( 'optional', 'wpcf7' ) ); ?>)<br />
  156. <input type="checkbox" name="size:s" class="exclusive option" />&nbsp;<?php echo esc_html( __( "Small", 'wpcf7' ) ); ?>&emsp;
  157. <input type="checkbox" name="size:m" class="exclusive option" />&nbsp;<?php echo esc_html( __( "Medium", 'wpcf7' ) ); ?>&emsp;
  158. <input type="checkbox" name="size:l" class="exclusive option" />&nbsp;<?php echo esc_html( __( "Large", 'wpcf7' ) ); ?>
  159. </td></tr>
  160. </table>
  161. <table class="scope captchar">
  162. <caption><?php echo esc_html( __( "Input field settings", 'wpcf7' ) ); ?></caption>
  163. <tr>
  164. <td><code>id</code> (<?php echo esc_html( __( 'optional', 'wpcf7' ) ); ?>)<br />
  165. <input type="text" name="id" class="idvalue oneline option" /></td>
  166. <td><code>class</code> (<?php echo esc_html( __( 'optional', 'wpcf7' ) ); ?>)<br />
  167. <input type="text" name="class" class="classvalue oneline option" /></td>
  168. </tr>
  169. <tr>
  170. <td><code>size</code> (<?php echo esc_html( __( 'optional', 'wpcf7' ) ); ?>)<br />
  171. <input type="number" name="size" class="numeric oneline option" min="1" /></td>
  172. <td><code>maxlength</code> (<?php echo esc_html( __( 'optional', 'wpcf7' ) ); ?>)<br />
  173. <input type="number" name="maxlength" class="numeric oneline option" min="1" /></td>
  174. </tr>
  175. </table>
  176. <div class="tg-tag"><?php echo esc_html( __( "Copy this code and paste it into the form left.", 'wpcf7' ) ); ?>
  177. <br />1) <?php echo esc_html( __( "For image", 'wpcf7' ) ); ?>
  178. <input type="text" name="captchac" class="tag" readonly="readonly" onfocus="this.select()" />
  179. <br />2) <?php echo esc_html( __( "For input field", 'wpcf7' ) ); ?>
  180. <input type="text" name="captchar" class="tag" readonly="readonly" onfocus="this.select()" />
  181. </div>
  182. </form>
  183. </div>
  184. <?php
  185. }
  186. /* Warning message */
  187. add_action( 'wpcf7_admin_notices', 'wpcf7_captcha_display_warning_message' );
  188. function wpcf7_captcha_display_warning_message() {
  189. if ( empty( $_GET['post'] ) || ! $contact_form = wpcf7_contact_form( $_GET['post'] ) )
  190. return;
  191. $has_tags = (bool) $contact_form->form_scan_shortcode(
  192. array( 'type' => array( 'captchac' ) ) );
  193. if ( ! $has_tags )
  194. return;
  195. if ( ! class_exists( 'ReallySimpleCaptcha' ) )
  196. return;
  197. $uploads_dir = wpcf7_captcha_tmp_dir();
  198. wpcf7_init_captcha();
  199. if ( ! is_dir( $uploads_dir ) || ! is_writable( $uploads_dir ) ) {
  200. $message = sprintf( __( 'This contact form contains CAPTCHA fields, but the temporary folder for the files (%s) does not exist or is not writable. You can create the folder or change its permission manually.', 'wpcf7' ), $uploads_dir );
  201. echo '<div class="error"><p><strong>' . esc_html( $message ) . '</strong></p></div>';
  202. }
  203. if ( ! function_exists( 'imagecreatetruecolor' ) || ! function_exists( 'imagettftext' ) ) {
  204. $message = __( 'This contact form contains CAPTCHA fields, but the necessary libraries (GD and FreeType) are not available on your server.', 'wpcf7' );
  205. echo '<div class="error"><p><strong>' . esc_html( $message ) . '</strong></p></div>';
  206. }
  207. }
  208. /* CAPTCHA functions */
  209. function wpcf7_init_captcha() {
  210. global $wpcf7_captcha;
  211. if ( ! class_exists( 'ReallySimpleCaptcha' ) )
  212. return false;
  213. if ( ! is_object( $wpcf7_captcha ) )
  214. $wpcf7_captcha = new ReallySimpleCaptcha();
  215. $dir = trailingslashit( wpcf7_captcha_tmp_dir() );
  216. $wpcf7_captcha->tmp_dir = $dir;
  217. if ( is_callable( array( $wpcf7_captcha, 'make_tmp_dir' ) ) )
  218. return $wpcf7_captcha->make_tmp_dir();
  219. if ( ! wp_mkdir_p( $dir ) )
  220. return false;
  221. $htaccess_file = $dir . '.htaccess';
  222. if ( file_exists( $htaccess_file ) )
  223. return true;
  224. if ( $handle = @fopen( $htaccess_file, 'w' ) ) {
  225. fwrite( $handle, 'Order deny,allow' . "\n" );
  226. fwrite( $handle, 'Deny from all' . "\n" );
  227. fwrite( $handle, '<Files ~ "^[0-9A-Za-z]+\\.(jpeg|gif|png)$">' . "\n" );
  228. fwrite( $handle, ' Allow from all' . "\n" );
  229. fwrite( $handle, '</Files>' . "\n" );
  230. fclose( $handle );
  231. }
  232. return true;
  233. }
  234. function wpcf7_captcha_tmp_dir() {
  235. if ( defined( 'WPCF7_CAPTCHA_TMP_DIR' ) )
  236. return WPCF7_CAPTCHA_TMP_DIR;
  237. else
  238. return wpcf7_upload_dir( 'dir' ) . '/wpcf7_captcha';
  239. }
  240. function wpcf7_captcha_tmp_url() {
  241. if ( defined( 'WPCF7_CAPTCHA_TMP_URL' ) )
  242. return WPCF7_CAPTCHA_TMP_URL;
  243. else
  244. return wpcf7_upload_dir( 'url' ) . '/wpcf7_captcha';
  245. }
  246. function wpcf7_generate_captcha( $options = null ) {
  247. global $wpcf7_captcha;
  248. if ( ! wpcf7_init_captcha() )
  249. return false;
  250. if ( ! is_dir( $wpcf7_captcha->tmp_dir ) || ! is_writable( $wpcf7_captcha->tmp_dir ) )
  251. return false;
  252. $img_type = imagetypes();
  253. if ( $img_type & IMG_PNG )
  254. $wpcf7_captcha->img_type = 'png';
  255. elseif ( $img_type & IMG_GIF )
  256. $wpcf7_captcha->img_type = 'gif';
  257. elseif ( $img_type & IMG_JPG )
  258. $wpcf7_captcha->img_type = 'jpeg';
  259. else
  260. return false;
  261. if ( is_array( $options ) ) {
  262. if ( isset( $options['img_size'] ) )
  263. $wpcf7_captcha->img_size = $options['img_size'];
  264. if ( isset( $options['base'] ) )
  265. $wpcf7_captcha->base = $options['base'];
  266. if ( isset( $options['font_size'] ) )
  267. $wpcf7_captcha->font_size = $options['font_size'];
  268. if ( isset( $options['font_char_width'] ) )
  269. $wpcf7_captcha->font_char_width = $options['font_char_width'];
  270. if ( isset( $options['fg'] ) )
  271. $wpcf7_captcha->fg = $options['fg'];
  272. if ( isset( $options['bg'] ) )
  273. $wpcf7_captcha->bg = $options['bg'];
  274. }
  275. $prefix = mt_rand();
  276. $captcha_word = $wpcf7_captcha->generate_random_word();
  277. return $wpcf7_captcha->generate_image( $prefix, $captcha_word );
  278. }
  279. function wpcf7_check_captcha( $prefix, $response ) {
  280. global $wpcf7_captcha;
  281. if ( ! wpcf7_init_captcha() )
  282. return false;
  283. return $wpcf7_captcha->check( $prefix, $response );
  284. }
  285. function wpcf7_remove_captcha( $prefix ) {
  286. global $wpcf7_captcha;
  287. if ( ! wpcf7_init_captcha() )
  288. return false;
  289. if ( preg_match( '/[^0-9]/', $prefix ) ) // Contact Form 7 generates $prefix with mt_rand()
  290. return false;
  291. $wpcf7_captcha->remove( $prefix );
  292. }
  293. function wpcf7_cleanup_captcha_files() {
  294. global $wpcf7_captcha;
  295. if ( ! wpcf7_init_captcha() )
  296. return false;
  297. if ( is_callable( array( $wpcf7_captcha, 'cleanup' ) ) )
  298. return $wpcf7_captcha->cleanup();
  299. $dir = trailingslashit( wpcf7_captcha_tmp_dir() );
  300. if ( ! is_dir( $dir ) || ! is_readable( $dir ) || ! is_writable( $dir ) )
  301. return false;
  302. if ( $handle = @opendir( $dir ) ) {
  303. while ( false !== ( $file = readdir( $handle ) ) ) {
  304. if ( ! preg_match( '/^[0-9]+\.(php|txt|png|gif|jpeg)$/', $file ) )
  305. continue;
  306. $stat = @stat( $dir . $file );
  307. if ( $stat['mtime'] + 3600 < time() ) // 3600 secs == 1 hour
  308. @unlink( $dir . $file );
  309. }
  310. closedir( $handle );
  311. }
  312. }
  313. if ( ! is_admin() && 'GET' == $_SERVER['REQUEST_METHOD'] )
  314. wpcf7_cleanup_captcha_files();
  315. function wpcf7_captchac_options( $options ) {
  316. if ( ! is_array( $options ) )
  317. return array();
  318. $op = array();
  319. $image_size_array = preg_grep( '%^size:[smlSML]$%', $options );
  320. if ( $image_size = array_shift( $image_size_array ) ) {
  321. preg_match( '%^size:([smlSML])$%', $image_size, $is_matches );
  322. switch ( strtolower( $is_matches[1] ) ) {
  323. case 's':
  324. $op['img_size'] = array( 60, 20 );
  325. $op['base'] = array( 6, 15 );
  326. $op['font_size'] = 11;
  327. $op['font_char_width'] = 13;
  328. break;
  329. case 'l':
  330. $op['img_size'] = array( 84, 28 );
  331. $op['base'] = array( 6, 20 );
  332. $op['font_size'] = 17;
  333. $op['font_char_width'] = 19;
  334. break;
  335. case 'm':
  336. default:
  337. $op['img_size'] = array( 72, 24 );
  338. $op['base'] = array( 6, 18 );
  339. $op['font_size'] = 14;
  340. $op['font_char_width'] = 15;
  341. }
  342. }
  343. $fg_color_array = preg_grep( '%^fg:#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$%', $options );
  344. if ( $fg_color = array_shift( $fg_color_array ) ) {
  345. preg_match( '%^fg:#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$%', $fg_color, $fc_matches );
  346. if ( 3 == strlen( $fc_matches[1] ) ) {
  347. $r = substr( $fc_matches[1], 0, 1 );
  348. $g = substr( $fc_matches[1], 1, 1 );
  349. $b = substr( $fc_matches[1], 2, 1 );
  350. $op['fg'] = array( hexdec( $r . $r ), hexdec( $g . $g ), hexdec( $b . $b ) );
  351. } elseif ( 6 == strlen( $fc_matches[1] ) ) {
  352. $r = substr( $fc_matches[1], 0, 2 );
  353. $g = substr( $fc_matches[1], 2, 2 );
  354. $b = substr( $fc_matches[1], 4, 2 );
  355. $op['fg'] = array( hexdec( $r ), hexdec( $g ), hexdec( $b ) );
  356. }
  357. }
  358. $bg_color_array = preg_grep( '%^bg:#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$%', $options );
  359. if ( $bg_color = array_shift( $bg_color_array ) ) {
  360. preg_match( '%^bg:#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$%', $bg_color, $bc_matches );
  361. if ( 3 == strlen( $bc_matches[1] ) ) {
  362. $r = substr( $bc_matches[1], 0, 1 );
  363. $g = substr( $bc_matches[1], 1, 1 );
  364. $b = substr( $bc_matches[1], 2, 1 );
  365. $op['bg'] = array( hexdec( $r . $r ), hexdec( $g . $g ), hexdec( $b . $b ) );
  366. } elseif ( 6 == strlen( $bc_matches[1] ) ) {
  367. $r = substr( $bc_matches[1], 0, 2 );
  368. $g = substr( $bc_matches[1], 2, 2 );
  369. $b = substr( $bc_matches[1], 4, 2 );
  370. $op['bg'] = array( hexdec( $r ), hexdec( $g ), hexdec( $b ) );
  371. }
  372. }
  373. return $op;
  374. }
  375. $wpcf7_captcha = null;
  376. ?>