PluginProbe
Booking Calendar / 10.1.3
Booking Calendar v10.1.3
11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 All 204 releases
booking / js / captcha / captcha.php

captcha.php in Booking Calendar 10.1.3, at js/captcha/captcha.php

402 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Really Simple CAPTCHA
4 Plugin URI: http://contactform7.com/captcha/
5 Description: Really Simple CAPTCHA is a CAPTCHA module intended to be called from other plugins. It is originally created for my Contact Form 7 plugin.
6 Author: Takayuki Miyoshi
7 Author URI: http://ideasilo.wordpress.com/
8 Text Domain: really-simple-captcha
9 Version: 1.9
10 */
11
12 /* Copyright 2007-2016 Takayuki Miyoshi (email: takayukister at gmail.com)
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 */
28
29 define( 'WPDEVREALLYSIMPLECAPTCHA_VERSION', '1.9.0.1' );
30
31 class wpdevReallySimpleCaptcha {
32
33 public $chars;
34 public $char_length;
35 public $fonts;
36 public $tmp_dir;
37 public $img_size;
38 public $bg;
39 public $fg;
40 public $base;
41 public $font_size;
42 public $font_char_width;
43 public $img_type;
44 public $file_mode;
45 public $answer_file_mode;
46
47 public function __construct() {
48
49 /* Characters available in images */
50 $this->chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
51
52 /* Length of a word in an image */
53 $this->char_length = 4;
54
55 /* Array of fonts. Randomly picked up per character */
56 $this->fonts = array(
57 dirname( __FILE__ ) . '/gentium/GenBkBasR.ttf',
58 dirname( __FILE__ ) . '/gentium/GenBkBasI.ttf',
59 dirname( __FILE__ ) . '/gentium/GenBkBasBI.ttf',
60 dirname( __FILE__ ) . '/gentium/GenBkBasB.ttf' );
61
62 /* Directory temporary keeping CAPTCHA images and corresponding text files */
63 $this->tmp_dir = path_join( dirname( __FILE__ ), 'tmp' );
64
65 /* Array of CAPTCHA image size. Width and height */
66 $this->img_size = array( 72, 24 );
67
68 /* Background color of CAPTCHA image. RGB color 0-255 */
69 $this->bg = array( 255, 255, 255 );
70
71 /* Foreground (character) color of CAPTCHA image. RGB color 0-255 */
72 $this->fg = array( 0, 0, 0 );
73
74 //FixIn: 10.0.0.54
75 if ( ( function_exists( 'get_bk_option' ) ) && ( 'wpbc_theme_dark_1' === get_bk_option( 'booking_form_theme' ) ) ) {
76 $this->bg = array( 39, 39, 39 );
77 $this->fg = array( 255, 255, 255 );
78 }
79
80 /* Coordinates for a text in an image. I don't know the meaning. Just adjust. */
81 $this->base = array( 6, 18 );
82
83 /* Font size */
84 $this->font_size = 14;
85
86 /* Width of a character */
87 $this->font_char_width = 15;
88
89 /* Image type. 'png', 'gif' or 'jpeg' */
90 $this->img_type = 'png';
91
92 /* Mode of temporary image files */
93 $this->file_mode = 0644;
94
95 /* Mode of temporary answer text files */
96 $this->answer_file_mode = 0640;
97 }
98
99 /**
100 * Generate and return a random word.
101 *
102 * @return string Random word with $chars characters x $char_length length
103 */
104 public function generate_random_word() {
105 $word = '';
106
107 for ( $i = 0; $i < $this->char_length; $i++ ) {
108 $pos = mt_rand( 0, strlen( $this->chars ) - 1 );
109 $char = $this->chars[$pos];
110 $word .= $char;
111 }
112
113 return $word;
114 }
115
116 /**
117 * Generate CAPTCHA image and corresponding answer file.
118 *
119 * @param string $prefix File prefix used for both files
120 * @param string $word Random word generated by generate_random_word()
121 * @return string|bool The file name of the CAPTCHA image. Return false if temp directory is not available.
122 */
123 public function generate_image( $prefix, $word ) {
124 if ( ! $this->make_tmp_dir() ) {
125 return false;
126 }
127
128 $this->cleanup();
129
130 $dir = trailingslashit( $this->tmp_dir );
131 $filename = null;
132
133 if ( $im = imagecreatetruecolor( $this->img_size[0], $this->img_size[1] ) ) {
134
135 $bg = imagecolorallocate( $im, $this->bg[0], $this->bg[1], $this->bg[2] );
136 $fg = imagecolorallocate( $im, $this->fg[0], $this->fg[1], $this->fg[2] );
137
138 imagefill( $im, 0, 0, $bg );
139
140 $x = $this->base[0] + mt_rand( -2, 2 );
141
142 for ( $i = 0; $i < strlen( $word ); $i++ ) {
143 $font = $this->fonts[array_rand( $this->fonts )];
144 $font = $this->normalize_path( $font );
145
146 imagettftext( $im, $this->font_size, mt_rand( -12, 12 ), $x,
147 $this->base[1] + mt_rand( -2, 2 ), $fg, $font, $word[$i] );
148 $x += $this->font_char_width;
149 }
150
151 switch ( $this->img_type ) {
152 case 'jpeg':
153 $filename = sanitize_file_name( $prefix . '.jpeg' );
154 $file = $this->normalize_path( $dir . $filename );
155 imagejpeg( $im, $file );
156 break;
157 case 'gif':
158 $filename = sanitize_file_name( $prefix . '.gif' );
159 $file = $this->normalize_path( $dir . $filename );
160 imagegif( $im, $file );
161 break;
162 case 'png':
163 default:
164 $filename = sanitize_file_name( $prefix . '.png' );
165 $file = $this->normalize_path( $dir . $filename );
166 imagepng( $im, $file );
167 }
168
169 imagedestroy( $im );
170 @chmod( $file, $this->file_mode );
171 }
172
173 $this->generate_answer_file( $prefix, $word );
174
175 return $filename;
176 }
177
178 /**
179 * Generate answer file corresponding to CAPTCHA image.
180 *
181 * @param string $prefix File prefix used for answer file
182 * @param string $word Random word generated by generate_random_word()
183 */
184 public function generate_answer_file( $prefix, $word ) {
185 $dir = trailingslashit( $this->tmp_dir );
186 $answer_file = $dir . sanitize_file_name( $prefix . '.txt' );
187 $answer_file = $this->normalize_path( $answer_file );
188
189 if ( $fh = @fopen( $answer_file, 'w' ) ) {
190 $word = strtoupper( $word );
191 $salt = wp_generate_password( 64 );
192 $hash = hash_hmac( 'md5', $word, $salt );
193
194 $code = $salt . '|' . $hash;
195
196 fwrite( $fh, $code );
197 fclose( $fh );
198 }
199
200 @chmod( $answer_file, $this->answer_file_mode );
201 }
202
203 /**
204 * Check a response against the code kept in the temporary file.
205 *
206 * @param string $prefix File prefix used for both files
207 * @param string $response CAPTCHA response
208 * @return bool Return true if the two match, otherwise return false.
209 */
210 public function check( $prefix, $response ) {
211 if ( 0 == strlen( $prefix ) ) {
212 return false;
213 }
214
215 $response = str_replace( array( " ", "\t" ), '', $response );
216 $response = strtoupper( $response );
217
218 $dir = trailingslashit( $this->tmp_dir );
219 $filename = sanitize_file_name( $prefix . '.txt' );
220 $file = $this->normalize_path( $dir . $filename );
221
222 if ( @is_readable( $file ) && ( $code = file_get_contents( $file ) ) ) {
223 $code = explode( '|', $code, 2 );
224
225 $salt = $code[0];
226 $hash = $code[1];
227
228 if ( hash_hmac( 'md5', $response, $salt ) == $hash ) {
229 return true;
230 }
231 }
232
233 return false;
234 }
235
236 /**
237 * Remove temporary files with given prefix.
238 *
239 * @param string $prefix File prefix
240 */
241 public function remove( $prefix ) {
242 $dir = trailingslashit( $this->tmp_dir );
243 $suffixes = array( '.jpeg', '.gif', '.png', '.php', '.txt' );
244
245 foreach ( $suffixes as $suffix ) {
246 $filename = sanitize_file_name( $prefix . $suffix );
247 $file = $this->normalize_path( $dir . $filename );
248
249 if ( @is_file( $file ) ) {
250 @unlink( $file );
251 }
252 }
253 }
254
255 /**
256 * Clean up dead files older than given length of time.
257 *
258 * @param int $minutes Consider older files than this time as dead files
259 * @return int|bool The number of removed files. Return false if error occurred.
260 */
261 public function cleanup( $minutes = 60, $max = 100 ) {
262 $dir = trailingslashit( $this->tmp_dir );
263 $dir = $this->normalize_path( $dir );
264
265 if ( ! @is_dir( $dir ) || ! @is_readable( $dir ) ) {
266 return false;
267 }
268
269 $is_win = ( 'WIN' === strtoupper( substr( PHP_OS, 0, 3 ) ) );
270
271 if ( ! ( $is_win ? win_is_writable( $dir ) : @is_writable( $dir ) ) ) {
272 return false;
273 }
274
275 $count = 0;
276
277 if ( $handle = @opendir( $dir ) ) {
278 while ( false !== ( $filename = readdir( $handle ) ) ) {
279 if ( ! preg_match( '/^[0-9]+\.(php|txt|png|gif|jpeg)$/', $filename ) ) {
280 continue;
281 }
282
283 $file = $this->normalize_path( $dir . $filename );
284
285 $stat = @stat( $file );
286 if ( ( $stat['mtime'] + $minutes * 60 ) < time() ) {
287 if ( ! @unlink( $file ) ) {
288 @chmod( $file, 0644 );
289 @unlink( $file );
290 }
291
292 $count += 1;
293 }
294
295 if ( $max <= $count ) {
296 break;
297 }
298 }
299
300 closedir( $handle );
301 }
302
303 return $count;
304 }
305
306 /**
307 * Make a temporary directory and generate .htaccess file in it.
308 *
309 * @return bool True on successful create, false on failure.
310 */
311 public function make_tmp_dir() {
312 $dir = trailingslashit( $this->tmp_dir );
313 $dir = $this->normalize_path( $dir );
314
315 if ( ! wp_mkdir_p( $dir ) ) {
316 return false;
317 }
318
319 $htaccess_file = $this->normalize_path( $dir . '.htaccess' );
320
321 if ( file_exists( $htaccess_file ) ) {
322 return true;
323 }
324
325 // FixIn: 8.7.7.5
326 if ( $handle = @fopen( $htaccess_file, 'w' ) ) {
327
328 fwrite( $handle, '# apache 2.2' . "\n" );
329 fwrite( $handle, '<IfModule !mod_authz_core.c>' . "\n" );
330 fwrite( $handle, ' Order deny,allow' . "\n" );
331 fwrite( $handle, ' Deny from all' . "\n" );
332 fwrite( $handle, ' <Files ~ "^[0-9A-Za-z]+\.(jpeg|gif|png)$">' . "\n" );
333 fwrite( $handle, ' Allow from all' . "\n" );
334 fwrite( $handle, ' </Files>' . "\n" );
335 fwrite( $handle, '</IfModule>' . "\n" );
336
337 fwrite( $handle, '# apache 2.4' . "\n" );
338 fwrite( $handle, '<IfModule mod_authz_core.c>' . "\n" );
339 fwrite( $handle, ' Require all denied' . "\n" );
340 fwrite( $handle, ' <Files ~ "^[0-9A-Za-z]+\.(jpeg|gif|png)$">' . "\n" );
341 fwrite( $handle, ' Require all granted' . "\n" );
342 fwrite( $handle, ' </Files>' . "\n" );
343 fwrite( $handle, '</IfModule>' . "\n" );
344
345 fclose( $handle );
346 }
347
348 /*
349 // Check Apache version
350 $apache_ver = '0';
351 if ( ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) && ( false !== strpos( $_SERVER['SERVER_SOFTWARE'], 'Apache/2.4' ) ) ) {
352
353 $apache_ver = explode( "Apache", $_SERVER['SERVER_SOFTWARE'] ); // Apache/1.3.29 (Unix) PHP
354 if ( isset( $apache_ver[1] ) ) {
355 $apache_ver = trim( $apache_ver[1], '/ ' );
356 $apache_ver = explode( " ", $apache_ver );
357 $apache_ver = trim( $apache_ver[0] );
358 } else {
359 $apache_ver = '0';
360 }
361 }
362 if ( version_compare( $apache_ver, '2.4', '>=' ) ) {
363 // Apache 2.4 or newer
364
365 if ( $handle = @fopen( $htaccess_file, 'w' ) ) {
366 fwrite( $handle, 'Require all denied' . "\n" );
367 fwrite( $handle, '<Files ~ "^[0-9A-Za-z]+\\.(jpeg|gif|png)$">' . "\n" );
368 fwrite( $handle, ' Require all granted' . "\n" );
369 fwrite( $handle, '</Files>' . "\n" );
370 fclose( $handle );
371 }
372 } else {
373
374 // Apache 2.2 or lower
375 if ( $handle = @fopen( $htaccess_file, 'w' ) ) {
376 fwrite( $handle, 'Order deny,allow' . "\n" );
377 fwrite( $handle, 'Deny from all' . "\n" );
378 fwrite( $handle, '<Files ~ "^[0-9A-Za-z]+\\.(jpeg|gif|png)$">' . "\n" );
379 fwrite( $handle, ' Allow from all' . "\n" );
380 fwrite( $handle, '</Files>' . "\n" );
381 fclose( $handle );
382 }
383 }
384 */
385 return true;
386 }
387
388 /**
389 * Normalize a filesystem path.
390 *
391 * This should be replaced by wp_normalize_path when the plugin's
392 * minimum requirement becomes WordPress 3.9 or higher.
393 *
394 * @param string $path Path to normalize.
395 * @return string Normalized path.
396 */
397 private function normalize_path( $path ) {
398 $path = str_replace( '\\', '/', $path );
399 $path = preg_replace( '|/+|', '/', $path );
400 return $path;
401 }
402 }