diff options
author | Andrey Andreev <narf@devilix.net> | 2017-11-07 14:30:36 +0100 |
---|---|---|
committer | Andrey Andreev <narf@devilix.net> | 2017-11-07 14:30:36 +0100 |
commit | 0ef93646615516ae2bc87e54894708adaa29700f (patch) | |
tree | 111b5d2980403c1401cf8dfe8756898df4ec2122 | |
parent | 271d6aea5a6c87381d1265a7c1074a383d1bed29 (diff) |
Implement data:image URIs in CAPTCHA helper
Also, switched to PNG by default and dropped JPEG; refactored image files GC.
Close #5200
-rw-r--r-- | system/helpers/captcha_helper.php | 74 | ||||
-rw-r--r-- | user_guide_src/source/changelog.rst | 7 | ||||
-rw-r--r-- | user_guide_src/source/helpers/captcha_helper.rst | 11 |
3 files changed, 56 insertions, 36 deletions
diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php index f98d8a4cd..1da4a923b 100644 --- a/system/helpers/captcha_helper.php +++ b/system/helpers/captcha_helper.php @@ -70,9 +70,9 @@ if ( ! function_exists('create_captcha')) 'img_height' => '30', 'img_alt' => 'captcha', 'font_path' => '', + 'font_size' => 16, 'expiration' => 7200, 'word_length' => 8, - 'font_size' => 16, 'img_id' => '', 'pool' => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 'colors' => array( @@ -95,30 +95,41 @@ if ( ! function_exists('create_captcha')) } } - if ($img_path === '' OR $img_url === '' - OR ! is_dir($img_path) OR ! is_really_writable($img_path) - OR ! extension_loaded('gd')) + if ( ! extension_loaded('gd')) { return FALSE; } - // ----------------------------------- - // Remove old images - // ----------------------------------- + if ($img_url !== '' OR $img_path !== '') + { + if ($img_path === '' OR $img_url === '' OR ! is_dir($img_path) OR ! is_really_writable($img_path)) + { + return FALSE; + } - $now = microtime(TRUE); + /** + * Remove old images + */ + $now = microtime(TRUE); - $current_dir = @opendir($img_path); - while ($filename = @readdir($current_dir)) - { - if (in_array(substr($filename, -4), array('.jpg', '.png')) - && (str_replace(array('.jpg', '.png'), '', $filename) + $expiration) < $now) + $current_dir = @opendir($img_path); + while ($filename = @readdir($current_dir)) { - @unlink($img_path.$filename); + if (preg_match('#^(?<ts>\d{10})\.png$#', $filename, $match) && ($match['ts'] + $expiration) < $now) + { + @unlink($img_path.$filename); + } } - } - @closedir($current_dir); + @closedir($current_dir); + + // This variable will later be used later to determine whether we write to disk or output a data:image URI + $img_filename = $now.'.png'; + } + else + { + $img_filename = NULL; + } // ----------------------------------- // Do we have a "word" yet? @@ -228,8 +239,8 @@ if ( ! function_exists('create_captcha')) // Determine angle and position // ----------------------------------- $length = strlen($word); - $angle = ($length >= 6) ? mt_rand(-($length-6), ($length-6)) : 0; - $x_axis = mt_rand(6, (360/$length)-16); + $angle = ($length >= 6) ? mt_rand(-($length - 6), ($length - 6)) : 0; + $x_axis = mt_rand(6, (360 / $length)-16); $y_axis = ($angle >= 0) ? mt_rand($img_height, $img_width) : mt_rand(6, $img_height); // Create image @@ -317,24 +328,31 @@ if ( ! function_exists('create_captcha')) // ----------------------------------- // Generate the image // ----------------------------------- - $img_url = rtrim($img_url, '/').'/'; - if (function_exists('imagejpeg')) - { - $img_filename = $now.'.jpg'; - imagejpeg($im, $img_path.$img_filename); - } - elseif (function_exists('imagepng')) + if (isset($img_filename)) { - $img_filename = $now.'.png'; + $img_src = rtrim($img_url, '/').'/'.$img_filename; imagepng($im, $img_path.$img_filename); } else { - return FALSE; + // I don't see an easier way to get the image contents without writing to file + $buffer = fopen('php://memory', 'wb+'); + imagepng($im, $buffer); + rewind($buffer); + $img_src = ''; + + // fread() will return an empty string (not FALSE) after the entire contents are read + while (strlen($read = fread($buffer, 4096))) + { + $img_src .= $read; + } + + fclose($buffer); + $img_src = 'data:image/png;base64,'.base64_encode($img_src); } - $img = '<img '.($img_id === '' ? '' : 'id="'.$img_id.'"').' src="'.$img_url.$img_filename.'" style="width: '.$img_width.'; height: '.$img_height .'; border: 0;" alt="'.$img_alt.'" />'; + $img = '<img '.($img_id === '' ? '' : 'id="'.$img_id.'"').' src="'.$img_src.'" 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); diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 0a625d861..0e766166e 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -89,7 +89,6 @@ Release Date: Not Released - Removed previously deprecated :doc:`Security Helper <helpers/security_helper>` function ``do_hash()`` (use PHP's native ``hash()`` instead). - Removed previously deprecated :doc:`File Helper <helpers/file_helper>` function ``read_file()`` (use PHP's native ``file_get_contents()`` instead). - Added new function :php:func:`ordinal_format()` to :doc:`Inflector Helper <helpers/inflector_helper>`. - - Added 'img_alt' option to :php:func`create_captcha()` :doc:`CAPTCHA Helper <helpers/captcha_helper>` with a default value of 'captcha'. - :doc:`Download Helper <helpers/download_helper>` changes include: @@ -113,6 +112,12 @@ Release Date: Not Released - Removed previously deprecated function ``form_prep()`` (use :php:func:`html_escape()` instead). - Removed the second (out of three) parameter from the :php:func:`form_upload()` function (it was never used). + - :doc:`CAPTCHA Helper <helpers/captcha_helper>` changes include: + + - Added 'img_alt' option with a default value of 'captcha'. + - Added ability to generate ``data:image/png;base64`` URIs instead of writing image files to disk. + - Updated to always create PNG images instead of JPEG. + Version 3.1.7 ============= diff --git a/user_guide_src/source/helpers/captcha_helper.rst b/user_guide_src/source/helpers/captcha_helper.rst index 986c1d3e1..bdf33c2a1 100644 --- a/user_guide_src/source/helpers/captcha_helper.rst +++ b/user_guide_src/source/helpers/captcha_helper.rst @@ -50,7 +50,8 @@ Once loaded you can generate a CAPTCHA like this:: echo $cap['image']; - The captcha function requires the GD image library. -- Only the **img_path** and **img_url** are required. +- The **img_path** and **img_url** are both required if you want to write images to disk. + To create ``data:image/png;base64`` images, simply omit these options. - If a **word** is not supplied, the function will generate a random ASCII string. You might put together your own word library that you can draw randomly from. @@ -89,10 +90,6 @@ Here is an example of usage with a database. On the page where the CAPTCHA will be shown you'll have something like this:: $this->load->helper('captcha'); - $vals = array( - 'img_path' => './captcha/', - 'img_url' => 'http://example.com/captcha/' - ); $cap = create_captcha($vals); $data = array( @@ -155,10 +152,10 @@ The following functions are available: The **image** is the actual image tag:: - <img src="http://example.com/captcha/12345.jpg" width="140" height="50" /> + <img src="data:image/png;base64,RHVtbXkgZXhhbXBsZQ==" width="140" height="50" /> The **time** is the micro timestamp used as the image name without the file extension. It will be a number like this: 1139612155.3422 The **word** is the word that appears in the captcha image, which if not - supplied to the function, will be a random string.
\ No newline at end of file + supplied to the function, will be a random string. |