8000 initialize · zerosdev/laravel-captcha@afd7c22 · GitHub
[go: up one dir, main page]

Skip to content

Commit afd7c22

Browse files
committed
initialize
1 parent 8e2b5ac commit afd7c22

File tree

5 files changed

+397
-0
lines changed

5 files changed

+397
-0
lines changed

composer.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "zerosdev/laravel-captcha",
3+
"description": "Captcha Generator for Laravel Framework",
4+
"type": "library",
5+
"homepage": "https://zeros.co.id",
6+
"license": "MIT",
7+
"support": {
8+
"issues": "https://github.com/ZerosDev/laravel-captcha/issues",
9+
"source": "https://github.com/ZerosDev/laravel-captcha"
10+
},
11+
"authors": [
12+
{
13+
"name": "Zeros Technology",
14+
"email": "admin@zeros.co.id"
15+
}
16+
],
17+
"minimum-stability": "dev",
18+
"require": {
19+
"php": ">=5.6",
20+
"laravel/framework": ">=5.2"
21+
},
22+
"autoload": {
23+
"psr-4" : {
24+
"ZerosDev\\LaravelCaptcha\\": "src"
25+
}
26+
},
27+
"require-dev": {
28+
"phpunit/phpunit": "^7"
29+
}
30+
}

src/Captcha.php

Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
<?php
2+
3+
namespace ZerosDev\LaravelCaptcha;
4+
5+
use Exception;
6+
use Illuminate\Support\Facades\Session;
7+
use Illuminate\Support\HtmlString;
8+
9+
class Captcha
10+
{
11+
/**
12+
* captcha id
13+
**/
14+
protected $id = null;
15+
16+
/**
17+
* image buffer data
18+
**/
19+
protected $bufferData = null;
20+
21+
/**
22+
* latest captcha session key
23+
**/
24+
protected $lastSessionKey = '';
25+
26+
/**
27+
* default captcha image width (px)
28+
**/
29+
protected $width;
30+
31+
/**
32+
* default captcha image height (px)
33+
**/
34+
protected $height;
35+
36+
/**
37+
* captcha characters
38+
**/
39+
protected $chars;
40+
41+
/**
42+
* default captcha length
43+
*/
44+
protected $captchaLength;
45+
46+
/**
47+
* captcha session name
48+
*/
49+
protected $sessionName;
50+
51+
/**
52+
* font name
53+
**/
54+
protected $font;
55+
56+
/**
57+
*
58+
* Initializing captcha
59+
*
60+
* @return void
61+
*
62+
**/
63+
64+
public function __construct()
65+
{
66+
$this->width = intval(config('captcha.width', 170));
67+
$this->height = intval(config('captcha.height', 50));
68+
$this->chars = config('captcha.chars', '123456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');
69+
$this->captchaLength = intval(config('captcha.length', 6));
70+
$this->font = config('captcha.font', 'Arimo-Bold.ttf');
71+
$this->sessionName = config('captcha.session_name', 'captcha');
72+
73+
$this->fontPath = dirname(__DIR__).'/storage/fonts/'.$this->font;
74+
75+
# Check if font is exists
76+
if( !file_exists($this->fontPath) || !is_file($this->fontPath) ) {
77+
throw new Exception("Font {$this->fontPath} is not exists or can not be accessed. Kindly check the font file or directory/file permission");
78+
}
79+
80+
# check if captcha length > 0
81+
if( $this->captchaLength < 1 ) {
82+
throw new Exception("Captcha length must be greater than 0");
83+
}
84+
85+
# Start session if not started
86+
if( session_status() !== PHP_SESSION_ACTIVE )
87+
{
88+
if( !headers_sent() )
89+
{
90+
session_start();
91+
}
92+
else
93+
{
94+
throw new Exception("PHP session can not be started. Header already sent!");
95+
}
96+
}
97+
}
98+
99+
/**
100+
*
101+
* Set the character list
102+
*
103+
* @param string of character $chars
104+
* @return \ZerosDev\LaravelCaptcha\Captcha
105+
*
106+
**/
107+
108+
public function chars($chars)
109+
{
110+
$this->chars = $chars;
111+
return $this;
112+
}
113+
114+
/**
115+
*
116+
* Set the length of captcha code
117+
*
118+
* @param Int $length
119+
* @return \ZerosDev\LaravelCaptcha\Captcha
120+
*
121+
**/
122+
123+
public function length($length)
124+
{
125+
$this->captchaLength = intval($length);
126+
if( $this->captchaLength <= 0 ) {
127+
throw new Exception("Captcha length must be greater than 0");
128+
}
129+
return $this;
130+
}
131+
132+
/**
133+
*
134+
* Set the size of captcha image
135+
*
136+
* @param integer $width
137+
* @param integer $height
138+
* @return \ZerosDev\LaravelCaptcha\Captcha
139+
*
140+
**/
141+
142+
public function size($width, $height)
143+
{
144+
$this->width = intval($width);
145+
$this->height = intval($height);
146+
return $this;
147+
}
148+
149+
/**
150+
*
151+
* Generating captcha
152+
*
153+
* @return \ZerosDev\LaravelCaptcha\Captcha
154+
*
155+
**/
156+
157+
public function generate()
158+
{
159+
$image = imagecreatetruecolor($this->width, $this->height);
160+
$background_color = imagecolorallocate($image, 255, 255, 255);
161+
imagefilledrectangle($image, 0, 0, $this->width, $this->height, $background_color);
162+
$line_color = imagecolorallocate($image, 64, 64, 64);
163+
164+
for($i=0; $i<10; $i++)
165+
{
166+
imageline($image, 0, rand()%$this->height, $this->width, rand()%$this->height, $line_color);
167+
}
168+
169+
$pixel_color = imagecolorallocate($image, 0, 0, 255);
170+
171+
for($i=0; $i<1000; $i++)
172+
{
173+
imagesetpixel($image, rand()%$this->width, rand()%$this->height, $pixel_color);
174+
}
175+
176+
$len = strlen($this->chars);
177+
$text_color = imagecolorallocate($image, 0,0,0);
178+
$shadow_color = $grey = imagecolorallocate($image, 128, 128, 128);
179+
$word = '';
180+
$padding = 10;
181+
$spacing = (($this->width-$padding)/$this->captchaLength);
182+
183+
for($i=0; $i<$this->captchaLength; $i++)
184+
{
185+
$angle = mt_rand(-4, 4) * mt_rand(1,4);
186+
$sizeStart = (($this->height/2)-3);
187+
$sizeEnd = (($this->height/2)+3);
188+
$font_size = mt_rand($sizeStart, $sizeEnd);
189+
$letter = $this->chars[mt_rand(0, $len-1)];
190+
$xCoordinate = $i == 0 ? $padding : ($i*$spacing)+$padding;
191+
$lineHeight = ($this->height/2) + ($font_size/2);
192+
193+
imagettftext($image, $font_size, $angle, $xCoordinate, $lineHeight, $shadow_color, $this->font, $letter);
194+
imagettftext($image, $font_size, $angle, $xCoordinate, $lineHeight, $text_color, $this->font, $letter);
195+
$word .= $letter;
196+
}
197+
198+
$word = str_replace(' ', '', $word);
199+
200+
ob_start();
201+
imagepng($image);
202+
imagedestroy($image);
203+
204+
$this->bufferData = ob_get_clean();
205+
$this->id = uniqid().time();
206+
$this->lastSessionKey = '_'.$this->id;
207+
$cd = Session::has($this->sessionName) ? json_decode(Session::get($this->sessionName), true) : [];
208+
209+
if( count($cd) >= 20 )
210+
{
211+
Session::forget($this->sessionName);
212+
$cd = [];
213+
}
214+
215+
$cd[$this->lastSessionKey] = $word;
216+
$sessionValue = json_encode($cd);
217+
Session::put($this->sessionName, $sessionValue);
218+
219+
return $this;
220+
}
221+
222+
/**
223+
*
224+
* Get captcha image
225+
*
226+
* @return string of generated base64 image
227+
*
228+
**/
229+
230+
public function image()
231+
{
232+
return !empty($this->bufferData) ? 'data:image/png;base64, ' . base64_encode($this->bufferData) : null;
233+
}
234+
235+
/**
236+
*
237+
* Get captcha id
238+
*
239+
* @return string of captcha generation id
240+
*
241+
**/
242+
243+
public function id()
244+
{
245+
return !empty($this->id) ? $this->id : null;
246+
}
247+
248+
/**
249+
*
250+
* Generate html hidden input
251+
*
252+
* @param Captcha ID $id
253+
*
254+
* @return html
255+
*
256+
**/
257+
258+
public function form_field($captchaId = null, $elementId = 'captcha_id')
259+
{
260+
return HtmlString('<input type="hidden" id="'.$elementId.'" name="captcha_id" value="'.($captchaId ? $captchaId : $this->id).'">');
261+
}
262+
263+
/**
264+
*
265+
* Creating html tag of captcha image
266+
*
267+
* @param HTML Attributes (array) $attributes
268+
*
269+
* @return html
270+
*
271+
**/
272+
273+
public function html_image($attributes = [])
274+
{
275+
$html = '<img src="'.$this->image().'" ';
276+
277+
foreach($attributes as $name => $value)
278+
{
279+
$html .= $name.'="'.$value.'" ';
280+
}
281+
282+
$html .= '/>';
283+
284+
return HtmlString($html);
285+
}
286+
287+
/**
288+
*
289+
* Validating captcha
290+
*
291+
* @param Captcha ID $id
292+
* @param Captcha Code $captcha
293+
* @return boolean
294+
*
295+
**/
296+
297+
public function validate($id, $captcha)
298+
{
299+
$cd = Session::has($this->sessionName) ? Session::get($this->sessionName) : null;
300+
if( !empty($cd) )
301+
{
302+
$list = json_decode($cd, true);
303+
$key = '_'.$id;
304+
if( isset($list[$key]) )
305+
{
306+
$result = hash_equals($list[$key], $captcha) ? true : false;
307+
308+
if( $result )
309+
{
310+
unset($list[$key]);
311+
$sessionValue = json_encode($list);
312+
Session::put($this->sessionName, $sessionValue);
313+
}
314+
315+
return $result;
316+
}
317+
}
318+
319+
return false;
320+
}
321+
}

src/Facade.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace ZerosDev\LaravelCaptcha;
4+
5+
use Illuminate\Support\Facades\Facade as LaravelFacade;
6+
7+
class Facade extends LaravelFacade
8+
{
9+
protected static function getFacadeAccessor()
10+
{
11+
return 'Captcha';
12+
}
13+
}

0 commit comments

Comments
 (0)
0