summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Andreev <narf@devilix.net>2017-11-07 14:30:36 +0100
committerAndrey Andreev <narf@devilix.net>2017-11-07 14:30:36 +0100
commit0ef93646615516ae2bc87e54894708adaa29700f (patch)
tree111b5d2980403c1401cf8dfe8756898df4ec2122
parent271d6aea5a6c87381d1265a7c1074a383d1bed29 (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.php74
-rw-r--r--user_guide_src/source/changelog.rst7
-rw-r--r--user_guide_src/source/helpers/captcha_helper.rst11
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.