summaryrefslogtreecommitdiffstats
path: root/system/helpers/captcha_helper.php
diff options
context:
space:
mode:
Diffstat (limited to 'system/helpers/captcha_helper.php')
-rw-r--r--system/helpers/captcha_helper.php107
1 files changed, 98 insertions, 9 deletions
diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php
index 201987ac8..f98d8a4cd 100644
--- a/system/helpers/captcha_helper.php
+++ b/system/helpers/captcha_helper.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
- * @link http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Helpers
* @category Helpers
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/helpers/captcha_helper.html
+ * @link https://codeigniter.com/user_guide/helpers/captcha_helper.html
*/
// ------------------------------------------------------------------------
@@ -68,6 +68,7 @@ if ( ! function_exists('create_captcha'))
'img_url' => '',
'img_width' => '150',
'img_height' => '30',
+ 'img_alt' => 'captcha',
'font_path' => '',
'expiration' => 7200,
'word_length' => 8,
@@ -110,7 +111,8 @@ if ( ! function_exists('create_captcha'))
$current_dir = @opendir($img_path);
while ($filename = @readdir($current_dir))
{
- if (substr($filename, -4) === '.jpg' && (str_replace('.jpg', '', $filename) + $expiration) < $now)
+ if (in_array(substr($filename, -4), array('.jpg', '.png'))
+ && (str_replace(array('.jpg', '.png'), '', $filename) + $expiration) < $now)
{
@unlink($img_path.$filename);
}
@@ -125,9 +127,96 @@ if ( ! function_exists('create_captcha'))
if (empty($word))
{
$word = '';
- for ($i = 0, $mt_rand_max = strlen($pool) - 1; $i < $word_length; $i++)
+ $pool_length = strlen($pool);
+ $rand_max = $pool_length - 1;
+
+ // PHP7 or a suitable polyfill
+ if (function_exists('random_int'))
+ {
+ try
+ {
+ for ($i = 0; $i < $word_length; $i++)
+ {
+ $word .= $pool[random_int(0, $rand_max)];
+ }
+ }
+ catch (Exception $e)
+ {
+ // This means fallback to the next possible
+ // alternative to random_int()
+ $word = '';
+ }
+ }
+ }
+
+ if (empty($word))
+ {
+ // Nobody will have a larger character pool than
+ // 256 characters, but let's handle it just in case ...
+ //
+ // No, I do not care that the fallback to mt_rand() can
+ // handle it; if you trigger this, you're very obviously
+ // trying to break it. -- Narf
+ if ($pool_length > 256)
+ {
+ return FALSE;
+ }
+
+ // We'll try using the operating system's PRNG first,
+ // which we can access through CI_Security::get_random_bytes()
+ $security = get_instance()->security;
+
+ // To avoid numerous get_random_bytes() calls, we'll
+ // just try fetching as much bytes as we need at once.
+ if (($bytes = $security->get_random_bytes($pool_length)) !== FALSE)
+ {
+ $byte_index = $word_index = 0;
+ while ($word_index < $word_length)
+ {
+ // Do we have more random data to use?
+ // It could be exhausted by previous iterations
+ // ignoring bytes higher than $rand_max.
+ if ($byte_index === $pool_length)
+ {
+ // No failures should be possible if the
+ // first get_random_bytes() call didn't
+ // return FALSE, but still ...
+ for ($i = 0; $i < 5; $i++)
+ {
+ if (($bytes = $security->get_random_bytes($pool_length)) === FALSE)
+ {
+ continue;
+ }
+
+ $byte_index = 0;
+ break;
+ }
+
+ if ($bytes === FALSE)
+ {
+ // Sadly, this means fallback to mt_rand()
+ $word = '';
+ break;
+ }
+ }
+
+ list(, $rand_index) = unpack('C', $bytes[$byte_index++]);
+ if ($rand_index > $rand_max)
+ {
+ continue;
+ }
+
+ $word .= $pool[$rand_index];
+ $word_index++;
+ }
+ }
+ }
+
+ if (empty($word))
+ {
+ for ($i = 0; $i < $word_length; $i++)
{
- $word .= $pool[mt_rand(0, $mt_rand_max)];
+ $word .= $pool[mt_rand(0, $rand_max)];
}
}
elseif ( ! is_string($word))
@@ -245,7 +334,7 @@ if ( ! function_exists('create_captcha'))
return FALSE;
}
- $img = '<img '.($img_id === '' ? '' : 'id="'.$img_id.'"').' src="'.$img_url.$img_filename.'" style="width: '.$img_width.'; height: '.$img_height .'; border: 0;" alt=" " />';
+ $img = '<img '.($img_id === '' ? '' : 'id="'.$img_id.'"').' src="'.$img_url.$img_filename.'" style="width: '.$img_width.'; height: '.$img_height .'; border: 0;" alt="'.$img_alt.'" />';
ImageDestroy($im);
return array('word' => $word, 'time' => $now, 'image' => $img, 'filename' => $img_filename);