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
+ }
0 commit comments