diff --git a/application/config/autoload.php b/application/config/autoload.php
index fa6ace1e8..e9566e74e 100644
--- a/application/config/autoload.php
+++ b/application/config/autoload.php
@@ -66,7 +66,7 @@
| $autoload['helper'] = array('url', 'file');
*/
-$autoload['helper'] = ['url', 'audit', 'date', 'dd', 'validation', 'general'];
+$autoload['helper'] = ['url', 'audit', 'date', 'dd', 'validation', 'general', 'captcha'];
/*
diff --git a/application/controllers/Mine.php b/application/controllers/Mine.php
index a2a60e676..6da29a345 100644
--- a/application/controllers/Mine.php
+++ b/application/controllers/Mine.php
@@ -805,6 +805,8 @@ public function cadastrar()
if ($this->form_validation->run('clientes') == false) {
$this->data['custom_error'] = (validation_errors() ? '
' . validation_errors() . '
' : false);
+ } elseif (strtolower($this->input->post('captcha')) != strtolower($this->session->userdata('captchaWord'))) {
+ $this->session->set_flashdata('error', 'Os caracteres da imagem não foram preenchidos corretamente ou o tempo máximo para preenchimento foi ultrapassado!');
} else {
$data = [
'nomeCliente' => set_value('nomeCliente'),
@@ -834,7 +836,36 @@ public function cadastrar()
$this->session->set_flashdata('error', 'Falha ao realizar cadastro!');
}
}
- $data = '';
+
+ $arrFont = ['ZXX_Noise.otf', 'karabine.ttf', 'capture.ttf', 'captcha.ttf'];
+ shuffle($arrFont);
+
+ $vals = [
+ 'img_path' => './assets/captcha-images/',
+ 'img_url' => base_url().'assets/captcha-images/',
+ 'font_path' => './assets/font/'.$arrFont[0],
+ 'img_width' => 150,
+ 'img_height' => 45,
+ 'expiration' => 7200,
+ 'word_length' => 6,
+ 'font_size' => 20,
+ 'img_id' => 'Imageid',
+ 'pool' => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'colors' => [
+ 'background' => [255, 255, 255],
+ 'border' => [255, 255, 255],
+ 'text' => [0, 0, 0],
+ 'grid' => [255, 40, 40],
+ ]
+ ];
+
+ $cap = create_captcha($vals);
+ $this->session->set_userdata('captchaWord', $cap['word']);
+
+ $data = [
+ 'captchaImage' => $cap['image']
+ ];
+
$this->load->view('conecte/cadastrar', $data);
}
diff --git a/application/helpers/captcha_helper.php b/application/helpers/captcha_helper.php
new file mode 100644
index 000000000..9fcbd1b2d
--- /dev/null
+++ b/application/helpers/captcha_helper.php
@@ -0,0 +1,353 @@
+ '',
+ 'img_path' => '',
+ 'img_url' => '',
+ 'img_width' => '150',
+ 'img_height' => '30',
+ 'font_path' => '',
+ 'expiration' => 7200,
+ 'word_length' => 8,
+ 'font_size' => 16,
+ 'img_id' => '',
+ 'pool' => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
+ 'colors' => array(
+ 'background' => array(255,255,255),
+ 'border' => array(153,102,102),
+ 'text' => array(204,153,153),
+ 'grid' => array(255,182,182)
+ )
+ );
+
+ foreach ($defaults as $key => $val)
+ {
+ if ( ! is_array($data) && empty($$key))
+ {
+ $$key = $val;
+ }
+ else
+ {
+ $$key = isset($data[$key]) ? $data[$key] : $val;
+ }
+ }
+
+ if ( ! extension_loaded('gd'))
+ {
+ log_message('error', 'create_captcha(): GD extension is not loaded.');
+ return FALSE;
+ }
+
+ if ($img_path === '' OR $img_url === '')
+ {
+ log_message('error', 'create_captcha(): $img_path and $img_url are required.');
+ return FALSE;
+ }
+
+ if ( ! is_dir($img_path) OR ! is_really_writable($img_path))
+ {
+ log_message('error', "create_captcha(): '{$img_path}' is not a dir, nor is it writable.");
+ return FALSE;
+ }
+
+ // -----------------------------------
+ // 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)
+ {
+ @unlink($img_path.$filename);
+ }
+ }
+
+ @closedir($current_dir);
+
+ // -----------------------------------
+ // Do we have a "word" yet?
+ // -----------------------------------
+
+ if (empty($word))
+ {
+ $word = '';
+ $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, $rand_max)];
+ }
+ }
+ elseif ( ! is_string($word))
+ {
+ $word = (string) $word;
+ }
+
+ // -----------------------------------
+ // 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);
+ $y_axis = ($angle >= 0) ? mt_rand($img_height, $img_width) : mt_rand(6, $img_height);
+
+ // Create image
+ // PHP.net recommends imagecreatetruecolor(), but it isn't always available
+ $im = function_exists('imagecreatetruecolor')
+ ? imagecreatetruecolor($img_width, $img_height)
+ : imagecreate($img_width, $img_height);
+
+ // -----------------------------------
+ // Assign colors
+ // ----------------------------------
+
+ is_array($colors) OR $colors = $defaults['colors'];
+
+ foreach (array_keys($defaults['colors']) as $key)
+ {
+ // Check for a possible missing value
+ is_array($colors[$key]) OR $colors[$key] = $defaults['colors'][$key];
+ $colors[$key] = imagecolorallocate($im, $colors[$key][0], $colors[$key][1], $colors[$key][2]);
+ }
+
+ // Create the rectangle
+ ImageFilledRectangle($im, 0, 0, $img_width, $img_height, $colors['background']);
+
+ // -----------------------------------
+ // Create the spiral pattern
+ // -----------------------------------
+ $theta = 1;
+ $thetac = 7;
+ $radius = 16;
+ $circles = 20;
+ $points = 32;
+
+ for ($i = 0, $cp = ($circles * $points) - 1; $i < $cp; $i++)
+ {
+ $theta += $thetac;
+ $rad = $radius * ($i / $points);
+ $x = ($rad * cos($theta)) + $x_axis;
+ $y = ($rad * sin($theta)) + $y_axis;
+ $theta += $thetac;
+ $rad1 = $radius * (($i + 1) / $points);
+ $x1 = ($rad1 * cos($theta)) + $x_axis;
+ $y1 = ($rad1 * sin($theta)) + $y_axis;
+ imageline($im, $x, $y, $x1, $y1, $colors['grid']);
+ $theta -= $thetac;
+ }
+
+ // -----------------------------------
+ // Write the text
+ // -----------------------------------
+
+ $use_font = ($font_path !== '' && file_exists($font_path) && function_exists('imagettftext'));
+ if ($use_font === FALSE)
+ {
+ ($font_size > 5) && $font_size = 5;
+ $x = mt_rand(0, $img_width / ($length / 3));
+ $y = 0;
+ }
+ else
+ {
+ ($font_size > 30) && $font_size = 30;
+ $x = mt_rand(0, $img_width / ($length / 1.5));
+ $y = $font_size + 2;
+ }
+
+ for ($i = 0; $i < $length; $i++)
+ {
+ if ($use_font === FALSE)
+ {
+ $y = mt_rand(0 , $img_height / 2);
+ imagestring($im, $font_size, $x, $y, $word[$i], $colors['text']);
+ $x += ($font_size * 2);
+ }
+ else
+ {
+ $y = mt_rand($img_height / 2, $img_height - 3);
+ imagettftext($im, $font_size, $angle, $x, $y, $colors['text'], $font_path, $word[$i]);
+ $x += $font_size;
+ }
+ }
+
+ // Create the border
+ imagerectangle($im, 0, 0, $img_width - 1, $img_height - 1, $colors['border']);
+
+ // -----------------------------------
+ // 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'))
+ {
+ $img_filename = $now.'.png';
+ imagepng($im, $img_path.$img_filename);
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ $img = '
';
+ ImageDestroy($im);
+
+ return array('word' => $word, 'time' => $now, 'image' => $img, 'filename' => $img_filename);
+ }
+}
diff --git a/application/views/conecte/cadastrar.php b/application/views/conecte/cadastrar.php
index ce92d772a..8b8613f4c 100644
--- a/application/views/conecte/cadastrar.php
+++ b/application/views/conecte/cadastrar.php
@@ -78,10 +78,9 @@
Cadastre-se no Sistema
-
@@ -253,6 +261,9 @@
},
cep: {
required: true
+ },
+ captcha: {
+ required: true
}
},
messages: {
@@ -289,8 +300,10 @@
},
cep: {
required: 'Campo Requerido.'
+ },
+ captcha: {
+ required: 'Campo Requerido.'
}
-
},
errorClass: "help-inline",
diff --git a/assets/captcha-images/index.html b/assets/captcha-images/index.html
new file mode 100644
index 000000000..7f684dff4
--- /dev/null
+++ b/assets/captcha-images/index.html
@@ -0,0 +1,10 @@
+
+
+ 403 Forbidden
+
+
+
+Directory access is forbidden.
+
+
+
diff --git a/assets/font/ZXX_Noise.otf b/assets/font/ZXX_Noise.otf
new file mode 100644
index 000000000..c48b02a90
Binary files /dev/null and b/assets/font/ZXX_Noise.otf differ
diff --git a/assets/font/captcha.ttf b/assets/font/captcha.ttf
new file mode 100644
index 000000000..8cfa4bc9d
Binary files /dev/null and b/assets/font/captcha.ttf differ
diff --git a/assets/font/capture.ttf b/assets/font/capture.ttf
new file mode 100644
index 000000000..041b3e388
Binary files /dev/null and b/assets/font/capture.ttf differ
diff --git a/assets/font/karabine.ttf b/assets/font/karabine.ttf
new file mode 100644
index 000000000..5c3d35c8c
Binary files /dev/null and b/assets/font/karabine.ttf differ