Subversion-Projekte lars-tiefland.ci

Revision

Revision 1257 | Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
68 lars 1
<?php
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
9
 * Copyright (c) 2014 - 2016, British Columbia Institute of Technology
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
32
 * @copyright	Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	https://codeigniter.com
35
 * @since	Version 1.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
 
40
/**
41
 * CodeIgniter CAPTCHA Helper
42
 *
43
 * @package		CodeIgniter
44
 * @subpackage	Helpers
45
 * @category	Helpers
46
 * @author		EllisLab Dev Team
47
 * @link		https://codeigniter.com/user_guide/helpers/captcha_helper.html
48
 */
49
 
50
// ------------------------------------------------------------------------
51
 
52
if ( ! function_exists('create_captcha'))
53
{
54
	/**
55
	 * Create CAPTCHA
56
	 *
57
	 * @param	array	$data		data for the CAPTCHA
58
	 * @param	string	$img_path	path to create the image in
59
	 * @param	string	$img_url	URL to the CAPTCHA image folder
60
	 * @param	string	$font_path	server path to font
61
	 * @return	string
62
	 */
63
	function create_captcha($data = '', $img_path = '', $img_url = '', $font_path = '')
64
	{
65
		$defaults = array(
66
			'word'		=> '',
67
			'img_path'	=> '',
68
			'img_url'	=> '',
69
			'img_width'	=> '150',
70
			'img_height'	=> '30',
71
			'font_path'	=> '',
72
			'expiration'	=> 7200,
73
			'word_length'	=> 8,
74
			'font_size'	=> 16,
75
			'img_id'	=> '',
76
			'pool'		=> '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
77
			'colors'	=> array(
78
				'background'	=> array(255,255,255),
79
				'border'	=> array(153,102,102),
80
				'text'		=> array(204,153,153),
81
				'grid'		=> array(255,182,182)
82
			)
83
		);
84
 
85
		foreach ($defaults as $key => $val)
86
		{
87
			if ( ! is_array($data) && empty($$key))
88
			{
89
				$$key = $val;
90
			}
91
			else
92
			{
93
				$$key = isset($data[$key]) ? $data[$key] : $val;
94
			}
95
		}
96
 
97
		if ($img_path === '' OR $img_url === ''
98
			OR ! is_dir($img_path) OR ! is_really_writable($img_path)
99
			OR ! extension_loaded('gd'))
100
		{
101
			return FALSE;
102
		}
103
 
104
		// -----------------------------------
105
		// Remove old images
106
		// -----------------------------------
107
 
108
		$now = microtime(TRUE);
109
 
110
		$current_dir = @opendir($img_path);
111
		while ($filename = @readdir($current_dir))
112
		{
113
			if (substr($filename, -4) === '.jpg' && (str_replace('.jpg', '', $filename) + $expiration) < $now)
114
			{
115
				@unlink($img_path.$filename);
116
			}
117
		}
118
 
119
		@closedir($current_dir);
120
 
121
		// -----------------------------------
122
		// Do we have a "word" yet?
123
		// -----------------------------------
124
 
125
		if (empty($word))
126
		{
127
			$word = '';
128
			$pool_length = strlen($pool);
129
			$rand_max = $pool_length - 1;
130
 
131
			// PHP7 or a suitable polyfill
132
			if (function_exists('random_int'))
133
			{
134
				try
135
				{
136
					for ($i = 0; $i < $word_length; $i++)
137
					{
138
						$word .= $pool[random_int(0, $rand_max)];
139
					}
140
				}
141
				catch (Exception $e)
142
				{
143
					// This means fallback to the next possible
144
					// alternative to random_int()
145
					$word = '';
146
				}
147
			}
148
		}
149
 
150
		if (empty($word))
151
		{
152
			// Nobody will have a larger character pool than
153
			// 256 characters, but let's handle it just in case ...
154
			//
155
			// No, I do not care that the fallback to mt_rand() can
156
			// handle it; if you trigger this, you're very obviously
157
			// trying to break it. -- Narf
158
			if ($pool_length > 256)
159
			{
160
				return FALSE;
161
			}
162
 
163
			// We'll try using the operating system's PRNG first,
164
			// which we can access through CI_Security::get_random_bytes()
165
			$security = get_instance()->security;
166
 
167
			// To avoid numerous get_random_bytes() calls, we'll
168
			// just try fetching as much bytes as we need at once.
169
			if (($bytes = $security->get_random_bytes($pool_length)) !== FALSE)
170
			{
171
				$byte_index = $word_index = 0;
172
				while ($word_index < $word_length)
173
				{
174
					// Do we have more random data to use?
175
					// It could be exhausted by previous iterations
176
					// ignoring bytes higher than $rand_max.
177
					if ($byte_index === $pool_length)
178
					{
179
						// No failures should be possible if the
180
						// first get_random_bytes() call didn't
181
						// return FALSE, but still ...
182
						for ($i = 0; $i < 5; $i++)
183
						{
184
							if (($bytes = $security->get_random_bytes($pool_length)) === FALSE)
185
							{
186
								continue;
187
							}
188
 
189
							$byte_index = 0;
190
							break;
191
						}
192
 
193
						if ($bytes === FALSE)
194
						{
195
							// Sadly, this means fallback to mt_rand()
196
							$word = '';
197
							break;
198
						}
199
					}
200
 
201
					list(, $rand_index) = unpack('C', $bytes[$byte_index++]);
202
					if ($rand_index > $rand_max)
203
					{
204
						continue;
205
					}
206
 
207
					$word .= $pool[$rand_index];
208
					$word_index++;
209
				}
210
			}
211
		}
212
 
213
		if (empty($word))
214
		{
215
			for ($i = 0; $i < $word_length; $i++)
216
			{
217
				$word .= $pool[mt_rand(0, $rand_max)];
218
			}
219
		}
220
		elseif ( ! is_string($word))
221
		{
222
			$word = (string) $word;
223
		}
224
 
225
		// -----------------------------------
226
		// Determine angle and position
227
		// -----------------------------------
228
		$length	= strlen($word);
229
		$angle	= ($length >= 6) ? mt_rand(-($length-6), ($length-6)) : 0;
230
		$x_axis	= mt_rand(6, (360/$length)-16);
231
		$y_axis = ($angle >= 0) ? mt_rand($img_height, $img_width) : mt_rand(6, $img_height);
232
 
233
		// Create image
234
		// PHP.net recommends imagecreatetruecolor(), but it isn't always available
235
		$im = function_exists('imagecreatetruecolor')
236
			? imagecreatetruecolor($img_width, $img_height)
237
			: imagecreate($img_width, $img_height);
238
 
239
		// -----------------------------------
240
		//  Assign colors
241
		// ----------------------------------
242
 
243
		is_array($colors) OR $colors = $defaults['colors'];
244
 
245
		foreach (array_keys($defaults['colors']) as $key)
246
		{
247
			// Check for a possible missing value
248
			is_array($colors[$key]) OR $colors[$key] = $defaults['colors'][$key];
249
			$colors[$key] = imagecolorallocate($im, $colors[$key][0], $colors[$key][1], $colors[$key][2]);
250
		}
251
 
252
		// Create the rectangle
253
		ImageFilledRectangle($im, 0, 0, $img_width, $img_height, $colors['background']);
254
 
255
		// -----------------------------------
256
		//  Create the spiral pattern
257
		// -----------------------------------
258
		$theta		= 1;
259
		$thetac		= 7;
260
		$radius		= 16;
261
		$circles	= 20;
262
		$points		= 32;
263
 
264
		for ($i = 0, $cp = ($circles * $points) - 1; $i < $cp; $i++)
265
		{
266
			$theta += $thetac;
267
			$rad = $radius * ($i / $points);
268
			$x = ($rad * cos($theta)) + $x_axis;
269
			$y = ($rad * sin($theta)) + $y_axis;
270
			$theta += $thetac;
271
			$rad1 = $radius * (($i + 1) / $points);
272
			$x1 = ($rad1 * cos($theta)) + $x_axis;
273
			$y1 = ($rad1 * sin($theta)) + $y_axis;
274
			imageline($im, $x, $y, $x1, $y1, $colors['grid']);
275
			$theta -= $thetac;
276
		}
277
 
278
		// -----------------------------------
279
		//  Write the text
280
		// -----------------------------------
281
 
282
		$use_font = ($font_path !== '' && file_exists($font_path) && function_exists('imagettftext'));
283
		if ($use_font === FALSE)
284
		{
285
			($font_size > 5) && $font_size = 5;
286
			$x = mt_rand(0, $img_width / ($length / 3));
287
			$y = 0;
288
		}
289
		else
290
		{
291
			($font_size > 30) && $font_size = 30;
292
			$x = mt_rand(0, $img_width / ($length / 1.5));
293
			$y = $font_size + 2;
294
		}
295
 
296
		for ($i = 0; $i < $length; $i++)
297
		{
298
			if ($use_font === FALSE)
299
			{
300
				$y = mt_rand(0 , $img_height / 2);
301
				imagestring($im, $font_size, $x, $y, $word[$i], $colors['text']);
302
				$x += ($font_size * 2);
303
			}
304
			else
305
			{
306
				$y = mt_rand($img_height / 2, $img_height - 3);
307
				imagettftext($im, $font_size, $angle, $x, $y, $colors['text'], $font_path, $word[$i]);
308
				$x += $font_size;
309
			}
310
		}
311
 
312
		// Create the border
313
		imagerectangle($im, 0, 0, $img_width - 1, $img_height - 1, $colors['border']);
314
 
315
		// -----------------------------------
316
		//  Generate the image
317
		// -----------------------------------
318
		$img_url = rtrim($img_url, '/').'/';
319
 
320
		if (function_exists('imagejpeg'))
321
		{
322
			$img_filename = $now.'.jpg';
323
			imagejpeg($im, $img_path.$img_filename);
324
		}
325
		elseif (function_exists('imagepng'))
326
		{
327
			$img_filename = $now.'.png';
328
			imagepng($im, $img_path.$img_filename);
329
		}
330
		else
331
		{
332
			return FALSE;
333
		}
334
 
335
		$img = '<img '.($img_id === '' ? '' : 'id="'.$img_id.'"').' src="'.$img_url.$img_filename.'" style="width: '.$img_width.'; height: '.$img_height .'; border: 0;" alt=" " />';
336
		ImageDestroy($im);
337
 
338
		return array('word' => $word, 'time' => $now, 'image' => $img, 'filename' => $img_filename);
339
	}
340
}