1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* PHP-Class hn_captcha Version 1.2, released 16-Apr-2004 |
4
|
|
|
* Author: Horst Nogajski, [email protected] |
5
|
|
|
* |
6
|
|
|
* License: GNU GPL (http://www.opensource.org/licenses/gpl-license.html) |
7
|
|
|
* Download: http://hn273.users.phpclasses.org/browse/package/1569.html |
8
|
|
|
* |
9
|
|
|
* If you find it useful, you might rate it on http://www.phpclasses.org/rate.html?package=1569 |
10
|
|
|
* If you use this class in a productional environment, you might drop me a note, so I can add a link to the page. |
11
|
|
|
* |
12
|
|
|
**/ |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* changes in version 1.1: |
16
|
|
|
* - added a new configuration-variable: maxrotation |
17
|
|
|
* - added a new configuration-variable: secretstring |
18
|
|
|
* - modified function get_try(): now ever returns a string of 16 chars |
19
|
|
|
* |
20
|
|
|
* changes in version 1.2: |
21
|
|
|
* - added a new configuration-variable: secretposition |
22
|
|
|
* - once more modified the function get_try(): generate a string of 32 chars length, |
23
|
|
|
* where at secretposition is the number of current-try. |
24
|
|
|
* Hopefully this is enough for hackprevention. |
25
|
|
|
* |
26
|
|
|
**/ |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* License: GNU GPL (http://www.opensource.org/licenses/gpl-license.html) |
30
|
|
|
* |
31
|
|
|
* This program is free software; |
32
|
|
|
* |
33
|
|
|
* you can redistribute it and/or modify it under the terms of the GNU General Public License |
34
|
|
|
* as published by the Free Software Foundation; either version 2 of the License, |
35
|
|
|
* or (at your option) any later version. |
36
|
|
|
* |
37
|
|
|
* This program is distributed in the hope that it will be useful, |
38
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
39
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
40
|
|
|
* |
41
|
|
|
* You should have received a copy of the GNU General Public License along with this program; |
42
|
|
|
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
43
|
|
|
* |
44
|
|
|
**/ |
45
|
|
|
|
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Tabsize: 4 |
49
|
|
|
* |
50
|
|
|
**/ |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* This class generates a picture to use in forms that perform CAPTCHA test |
54
|
|
|
* (Completely Automated Public Turing to tell Computers from Humans Apart). |
55
|
|
|
* After the test form is submitted a key entered by the user in a text field |
56
|
|
|
* is compared by the class to determine whether it matches the text in the picture. |
57
|
|
|
* |
58
|
|
|
* The class is a fork of the original released at www.phpclasses.org |
59
|
|
|
* by Julien Pachet with the name ocr_captcha. |
60
|
|
|
* |
61
|
|
|
* The following enhancements were added: |
62
|
|
|
* |
63
|
|
|
* - Support to make it work with GD library before version 2 |
64
|
|
|
* - Hacking prevention |
65
|
|
|
* - Optional use of Web safe colors |
66
|
|
|
* - Limit the number of users attempts |
67
|
|
|
* - Display an optional refresh link to generate a new picture with a different key |
68
|
|
|
* without counting to the user attempts limit verification |
69
|
|
|
* - Support the use of multiple random TrueType fonts |
70
|
|
|
* - Control the output image by only three parameters: number of text characters |
71
|
|
|
* and minimum and maximum size preserving the size proportion |
72
|
|
|
* - Preserve all request parameters passed to the page via the GET method, |
73
|
|
|
* so the CAPTCHA test can be added to existing scripts with minimal changes |
74
|
|
|
* - Added a debug option for testing the current configuration |
75
|
|
|
* |
76
|
|
|
* All the configuration settings are passed to the class in an array when the object instance is initialized. |
77
|
|
|
* |
78
|
|
|
* The class only needs two function calls to be used: display_form() and validate_submit(). |
79
|
|
|
* |
80
|
|
|
* The class comes with an examplefile. |
81
|
|
|
* If you don't have it: http://hn273.users.phpclasses.org/browse/package/1569.html |
82
|
|
|
* |
83
|
|
|
* @shortdesc Class that generate a captcha-image with text and a form to fill in this text |
84
|
|
|
* @public |
85
|
|
|
* @author Horst Nogajski, (mail: [email protected]) |
86
|
|
|
* @version 1.0 |
87
|
|
|
* @date 2004-April-10 |
88
|
|
|
* |
89
|
|
|
**/ |
90
|
|
|
class hn_captcha |
91
|
|
|
{ |
92
|
|
|
|
93
|
|
|
//////////////////////////////// |
94
|
|
|
// |
95
|
|
|
// PUBLIC PARAMS |
96
|
|
|
// |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* @shortdesc Absolute path to a Tempfolder (with trailing slash!). This must be writeable for PHP and also accessible via HTTP, because the image will be stored there. |
100
|
|
|
* @type string |
101
|
|
|
* @public |
102
|
|
|
* |
103
|
|
|
**/ |
104
|
|
|
var $tempfolder; |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* @shortdesc Absolute path to folder with TrueTypeFonts (with trailing slash!). This must be readable by PHP. |
108
|
|
|
* @type string |
109
|
|
|
* @public |
110
|
|
|
* |
111
|
|
|
**/ |
112
|
|
|
var $TTF_folder; |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @shortdesc A List with available TrueTypeFonts for random char-creation. |
116
|
|
|
* @type mixed[array|string] |
117
|
|
|
* @public |
118
|
|
|
* |
119
|
|
|
**/ |
120
|
|
|
var $TTF_RANGE = array('COMIC.TTF','JACOBITE.TTF','LYDIAN.TTF','MREARL.TTF','RUBBERSTAMP.TTF','ZINJARON.TTF'); |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @shortdesc How many chars the generated text should have |
124
|
|
|
* @type integer |
125
|
|
|
* @public |
126
|
|
|
* |
127
|
|
|
**/ |
128
|
|
|
var $chars = 6; |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @shortdesc The minimum size a Char should have |
132
|
|
|
* @type integer |
133
|
|
|
* @public |
134
|
|
|
* |
135
|
|
|
**/ |
136
|
|
|
var $minsize = 20; |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* @shortdesc The maximum size a Char can have |
140
|
|
|
* @type integer |
141
|
|
|
* @public |
142
|
|
|
* |
143
|
|
|
**/ |
144
|
|
|
var $maxsize = 40; |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* @shortdesc The maximum degrees a Char should be rotated. Set it to 30 means a random rotation between -30 and 30. |
148
|
|
|
* @type integer |
149
|
|
|
* @public |
150
|
|
|
* |
151
|
|
|
**/ |
152
|
|
|
var $maxrotation = 30; |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* @shortdesc Background noise On/Off (if is Off, a grid will be created) |
156
|
|
|
* @type boolean |
157
|
|
|
* @public |
158
|
|
|
* |
159
|
|
|
**/ |
160
|
|
|
var $noise = TRUE; |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* @shortdesc This will only use the 216 websafe color pallette for the image. |
164
|
|
|
* @type boolean |
165
|
|
|
* @public |
166
|
|
|
* |
167
|
|
|
**/ |
168
|
|
|
var $websafecolors = FALSE; |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* @shortdesc Switches language, available are 'en' and 'de'. You can easily add more. Look in CONSTRUCTOR. |
172
|
|
|
* @type string |
173
|
|
|
* @public |
174
|
|
|
* |
175
|
|
|
**/ |
176
|
|
|
var $lang = "de"; |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* @shortdesc If a user has reached this number of try's without success, he will moved to the $badguys_url |
180
|
|
|
* @type integer |
181
|
|
|
* @public |
182
|
|
|
* |
183
|
|
|
**/ |
184
|
|
|
var $maxtry = 3; |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* @shortdesc Gives the user the possibility to generate a new captcha-image. |
188
|
|
|
* @type boolean |
189
|
|
|
* @public |
190
|
|
|
* |
191
|
|
|
**/ |
192
|
|
|
var $refreshlink = TRUE; |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* @shortdesc If a user has reached his maximum try's, he will located to this url. |
196
|
|
|
* @type boolean |
197
|
|
|
* @public |
198
|
|
|
* |
199
|
|
|
**/ |
200
|
|
|
var $badguys_url = "/"; |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Number between 1 and 32 |
204
|
|
|
* |
205
|
|
|
* @shortdesc Defines the position of 'current try number' in (32-char-length)-string generated by function get_try() |
206
|
|
|
* @type integer |
207
|
|
|
* @public |
208
|
|
|
* |
209
|
|
|
**/ |
210
|
|
|
var $secretposition = 21; |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* @shortdesc The string is used to generate the md5-key. |
214
|
|
|
* @type string |
215
|
|
|
* @public |
216
|
|
|
* |
217
|
|
|
**/ |
218
|
|
|
var $secretstring = "This is a very secret string. Nobody should know it, =:)"; |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* @shortdesc Outputs configuration values for testing |
222
|
|
|
* @type boolean |
223
|
|
|
* @public |
224
|
|
|
* |
225
|
|
|
**/ |
226
|
|
|
var $debug = FALSE; |
227
|
|
|
|
228
|
|
|
|
229
|
|
|
|
230
|
|
|
//////////////////////////////// |
231
|
|
|
// |
232
|
|
|
// PRIVATE PARAMS |
233
|
|
|
// |
234
|
|
|
|
235
|
|
|
/** @private **/ |
236
|
|
|
var $lx; // width of picture |
237
|
|
|
/** @private **/ |
238
|
|
|
var $ly; // height of picture |
239
|
|
|
/** @private **/ |
240
|
|
|
var $jpegquality = 80; // image quality |
241
|
|
|
/** @private **/ |
242
|
|
|
var $noisefactor = 9; // this will multiplyed with number of chars |
243
|
|
|
/** @private **/ |
244
|
|
|
var $nb_noise; // number of background-noise-characters |
245
|
|
|
/** @private **/ |
246
|
|
|
var $TTF_file; // holds the current selected TrueTypeFont |
247
|
|
|
/** @private **/ |
248
|
|
|
var $msg1; |
249
|
|
|
/** @private **/ |
250
|
|
|
var $msg2; |
251
|
|
|
/** @private **/ |
252
|
|
|
var $buttontext; |
253
|
|
|
/** @private **/ |
254
|
|
|
var $refreshbuttontext; |
255
|
|
|
/** @private **/ |
256
|
|
|
var $public_K; |
257
|
|
|
/** @private **/ |
258
|
|
|
var $private_K; |
259
|
|
|
/** @private **/ |
260
|
|
|
var $key; // md5-key |
261
|
|
|
/** @private **/ |
262
|
|
|
var $public_key; // public key |
263
|
|
|
/** @private **/ |
264
|
|
|
var $filename; // filename of captcha picture |
265
|
|
|
/** @private **/ |
266
|
|
|
var $gd_version; // holds the Version Number of GD-Library |
267
|
|
|
/** @private **/ |
268
|
|
|
var $QUERY_STRING; // keeps the ($_GET) Querystring of the original Request |
269
|
|
|
/** @private **/ |
270
|
|
|
var $current_try = 0; |
271
|
|
|
/** @private **/ |
272
|
|
|
var $r; |
273
|
|
|
/** @private **/ |
274
|
|
|
var $g; |
275
|
|
|
/** @private **/ |
276
|
|
|
var $b; |
277
|
|
|
|
278
|
|
|
private static $validated = array(); |
279
|
|
|
|
280
|
|
|
|
281
|
|
|
//////////////////////////////// |
282
|
|
|
// |
283
|
|
|
// CONSTRUCTOR |
284
|
|
|
// |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* @shortdesc Extracts the config array and generate needed params. |
288
|
|
|
* @private |
289
|
|
|
* @type void |
290
|
|
|
* @return nothing |
|
|
|
|
291
|
|
|
* |
292
|
|
|
**/ |
293
|
|
|
function __construct($config,$secure=TRUE) |
|
|
|
|
294
|
|
|
{ |
295
|
|
|
|
296
|
|
|
// Test for GD-Library(-Version) |
297
|
|
|
$this->gd_version = $this->get_gd_version(); |
298
|
|
|
if($this->gd_version == 0) die("There is no GD-Library-Support enabled. The Captcha-Class cannot be used!"); |
|
|
|
|
299
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: The available GD-Library has major version ".$this->gd_version; |
300
|
|
|
|
301
|
|
|
|
302
|
|
|
// Hackprevention |
303
|
|
|
if( |
304
|
|
|
(isset($_GET['maxtry']) || isset($_POST['maxtry']) || isset($_COOKIE['maxtry'])) |
305
|
|
|
|| |
306
|
|
|
(isset($_GET['debug']) || isset($_POST['debug']) || isset($_COOKIE['debug'])) |
307
|
|
|
|| |
308
|
|
|
(isset($_GET['captcharefresh']) || isset($_COOKIE['captcharefresh'])) |
309
|
|
|
|| |
310
|
|
|
(isset($_POST['captcharefresh']) && isset($_POST['private_key'])) |
311
|
|
|
) |
312
|
|
|
{ |
313
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Buuh. You are a bad guy!"; |
314
|
|
|
if(isset($this->badguys_url) && !headers_sent()) header('location: '.$this->badguys_url); |
315
|
|
|
else die('Sorry.'); |
|
|
|
|
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
|
319
|
|
|
// extracts config array |
320
|
|
|
if(is_array($config)) |
321
|
|
|
{ |
322
|
|
|
if($secure && strcmp('4.2.0', phpversion()) < 0) |
323
|
|
|
{ |
324
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Extracts Config-Array in secure-mode!"; |
325
|
|
|
$valid = get_class_vars(get_class($this)); |
326
|
|
|
foreach($config as $k=>$v) |
327
|
|
|
{ |
328
|
|
|
if(array_key_exists($k,$valid)) $this->$k = $v; |
329
|
|
|
} |
330
|
|
|
} |
331
|
|
|
else |
332
|
|
|
{ |
333
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Extracts Config-Array in unsecure-mode!"; |
334
|
|
|
foreach($config as $k=>$v) $this->$k = $v; |
335
|
|
|
} |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
|
339
|
|
|
// check vars for maxtry, secretposition and min-max-size |
340
|
|
|
$this->maxtry = ($this->maxtry > 9 || $this->maxtry < 1) ? 3 : $this->maxtry; |
341
|
|
|
$this->secretposition = ($this->secretposition > 32 || $this->secretposition < 1) ? $this->maxtry : $this->secretposition; |
342
|
|
|
if($this->minsize > $this->maxsize) |
343
|
|
|
{ |
344
|
|
|
$temp = $this->minsize; |
345
|
|
|
$this->minsize = $this->maxsize; |
346
|
|
|
$this->maxsize = $temp; |
347
|
|
|
if($this->debug) echo "<br>-Captcha-Debug: Arrghh! What do you think I mean with min and max? Switch minsize with maxsize."; |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
|
351
|
|
|
// check TrueTypeFonts |
352
|
|
|
if(is_array($this->TTF_RANGE)) |
353
|
|
|
{ |
354
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Check given TrueType-Array! (".count($this->TTF_RANGE).")"; |
355
|
|
|
$temp = array(); |
356
|
|
|
foreach($this->TTF_RANGE as $k=>$v) |
357
|
|
|
{ |
358
|
|
|
if(is_readable($this->TTF_folder.$v)) $temp[] = $v; |
359
|
|
|
} |
360
|
|
|
$this->TTF_RANGE = $temp; |
361
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Valid TrueType-files: (".count($this->TTF_RANGE).")"; |
362
|
|
|
if(count($this->TTF_RANGE) < 1) die('No Truetypefont available for the CaptchaClass.'); |
|
|
|
|
363
|
|
|
} |
364
|
|
|
else |
365
|
|
|
{ |
366
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Check given TrueType-File! (".$this->TTF_RANGE.")"; |
367
|
|
|
if(!is_readable($this->TTF_folder.$this->TTF_RANGE)) die('No Truetypefont available for the CaptchaClass.'); |
|
|
|
|
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
// select first TrueTypeFont |
371
|
|
|
$this->change_TTF(); |
372
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Set current TrueType-File: (".$this->TTF_file.")"; |
373
|
|
|
|
374
|
|
|
|
375
|
|
|
// get number of noise-chars for background if is enabled |
376
|
|
|
$this->nb_noise = $this->noise ? ($this->chars * $this->noisefactor) : 0; |
377
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Set number of noise characters to: (".$this->nb_noise.")"; |
378
|
|
|
|
379
|
|
|
|
380
|
|
|
// set dimension of image |
381
|
|
|
$this->lx = ($this->chars + 1) * (int)(($this->maxsize + $this->minsize) / 1.5); |
382
|
|
|
$this->ly = (int)(2.4 * $this->maxsize); |
383
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Set image dimension to: (".$this->lx." x ".$this->ly.")"; |
384
|
|
|
|
385
|
|
|
|
386
|
|
|
// set all messages |
387
|
|
|
// (if you add a new language, you also want to add a line to the function "notvalid_msg()" at the end of the class!) |
388
|
|
|
$this->messages = array( |
|
|
|
|
389
|
|
|
'de'=>array( |
390
|
|
|
'msg1'=>'Du mu�t die <b>'.$this->chars.' Zeichen</b> im Bild, (Zahlen von <b>0 - 9</b> und Buchstaben von <b>A - F</b>),<br>in das Feld eintragen und das Formular abschicken um den Download zu starten.', |
391
|
|
|
'msg2'=>'Ohje, das kann ich nicht lesen. Bitte, generiere mir eine ', |
392
|
|
|
'buttontext'=>'abschicken', |
393
|
|
|
'refreshbuttontext'=>'neue ID' |
394
|
|
|
), |
395
|
|
|
'en'=>array( |
396
|
|
|
'msg1'=>'You must read and type the <b>'.$this->chars.' chars</b> within <b>0..9</b> and <b>A..F</b>, and submit the form.', |
397
|
|
|
'msg2'=>'Oh no, I cannot read this. Please, generate a ', |
398
|
|
|
'buttontext'=>'submit', |
399
|
|
|
'refreshbuttontext'=>'new ID' |
400
|
|
|
) |
401
|
|
|
); |
402
|
|
|
$this->msg1 = $this->messages[$this->lang]['msg1']; |
403
|
|
|
$this->msg2 = $this->messages[$this->lang]['msg2']; |
404
|
|
|
$this->buttontext = $this->messages[$this->lang]['buttontext']; |
405
|
|
|
$this->refreshbuttontext = $this->messages[$this->lang]['refreshbuttontext']; |
406
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Set messages to language: (".$this->lang.")"; |
407
|
|
|
|
408
|
|
|
|
409
|
|
|
// keep params from original GET-request |
410
|
|
|
// (if you use POST or COOKIES, you have to implement it yourself, sorry.) |
411
|
|
|
$this->QUERY_STRING = strlen(trim($_SERVER['QUERY_STRING'])) > 0 ? '?'.strip_tags($_SERVER['QUERY_STRING']) : ''; |
412
|
|
|
$refresh = $_SERVER['PHP_SELF'].$this->QUERY_STRING; |
|
|
|
|
413
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Keep this params from original GET-request: (".$this->QUERY_STRING.")"; |
414
|
|
|
|
415
|
|
|
|
416
|
|
|
// check Postvars |
417
|
|
View Code Duplication |
if(isset($_POST['public_key'])) $this->public_K = substr(strip_tags($_POST['public_key']),0,$this->chars); |
418
|
|
View Code Duplication |
if(isset($_POST['private_key'])) $this->private_K = substr(strip_tags($_POST['private_key']),0,$this->chars); |
419
|
|
|
$this->current_try = isset($_POST['hncaptcha']) ? $this->get_try() : 0; |
|
|
|
|
420
|
|
|
if(!isset($_POST['captcharefresh'])) $this->current_try++; |
421
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Check POST-vars, current try is: (".$this->current_try.")"; |
422
|
|
|
|
423
|
|
|
|
424
|
|
|
// generate Keys |
425
|
|
|
$this->key = md5($this->secretstring); |
426
|
|
|
do { |
427
|
|
|
$this->public_key = substr(md5(uniqid(rand(),true)), 0, $this->chars); |
428
|
|
|
} while (preg_match('/[1o0l]/i', $this->generate_private())); |
429
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Generate Keys, public key is: (".$this->public_key.")"; |
430
|
|
|
|
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
|
434
|
|
|
|
435
|
|
|
//////////////////////////////// |
436
|
|
|
// |
437
|
|
|
// PUBLIC METHODS |
438
|
|
|
// |
439
|
|
|
|
440
|
|
|
/** |
441
|
|
|
* |
442
|
|
|
* @shortdesc displays a complete form with captcha-picture |
443
|
|
|
* @public |
444
|
|
|
* @type void |
445
|
|
|
* @return HTML-Output |
|
|
|
|
446
|
|
|
* |
447
|
|
|
**/ |
448
|
|
|
function display_form() |
|
|
|
|
449
|
|
|
{ |
450
|
|
|
$try = $this->get_try(FALSE); |
451
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Generate a string which contains current try: ($try)"; |
452
|
|
|
$s = '<div id="captcha">'; |
453
|
|
|
$s .= '<form class="captcha" name="captcha1" action="'.$_SERVER['PHP_SELF'].$this->QUERY_STRING.'" method="POST">'."\n"; |
454
|
|
|
$s .= '<input type="hidden" name="hncaptcha" value="'.$try.'">'."\n"; |
455
|
|
|
$s .= '<p class="captcha_notvalid">'.$this->notvalid_msg().'</p>'; |
456
|
|
|
$s .= '<p class="captcha_1">'.$this->display_captcha()."</p>\n"; |
457
|
|
|
$s .= '<p class="captcha_1">'.$this->msg1.'</p>'; |
458
|
|
|
$s .= '<p class="captcha_1"><input class="captcha" type="text" name="private_key" value="" maxlength="'.$this->chars.'" size="'.$this->chars.'"> '; |
459
|
|
|
$s .= '<input class="captcha" type="submit" value="'.$this->buttontext.'">'."</p>\n"; |
460
|
|
|
$s .= '</form>'."\n"; |
461
|
|
|
if($this->refreshlink) |
462
|
|
|
{ |
463
|
|
|
$s .= '<form style="display:inline;" name="captcha2" action="'.$_SERVER['PHP_SELF'].$this->QUERY_STRING.'" method="POST">'."\n"; |
464
|
|
|
$s .= '<input type="hidden" name="captcharefresh" value="1"><input type="hidden" name="hncaptcha" value="'.$try.'">'."\n"; |
465
|
|
|
$s .= '<p class="captcha_2">'.$this->msg2; |
466
|
|
|
$s .= $this->public_key_input().'<input class="captcha" type="submit" value="'.$this->refreshbuttontext.'">'."</p>\n"; |
467
|
|
|
$s .= '</form>'."\n"; |
468
|
|
|
} |
469
|
|
|
$s .= '</div>'; |
470
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Output Form with captcha-image.<br><br>"; |
471
|
|
|
return $s; |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
|
475
|
|
|
/** |
476
|
|
|
* |
477
|
|
|
* @shortdesc validates POST-vars and return result |
478
|
|
|
* @public |
479
|
|
|
* @type integer |
480
|
|
|
* @return 0 = first call | 1 = valid submit | 2 = not valid | 3 = not valid and has reached maximum try's |
|
|
|
|
481
|
|
|
* |
482
|
|
|
**/ |
483
|
|
|
function validate_submit() |
484
|
|
|
{ |
485
|
|
|
if($this->check_captcha($this->public_K,$this->private_K)) |
486
|
|
|
{ |
487
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Validating submitted form returns: (1)"; |
488
|
|
|
return 1; |
489
|
|
|
} |
490
|
|
|
else |
491
|
|
|
{ |
492
|
|
|
if($this->current_try > $this->maxtry) |
493
|
|
|
{ |
494
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Validating submitted form returns: (3)"; |
495
|
|
|
return 3; |
496
|
|
|
} |
497
|
|
|
elseif($this->current_try > 0) |
498
|
|
|
{ |
499
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Validating submitted form returns: (2)"; |
500
|
|
|
return 2; |
501
|
|
|
} |
502
|
|
|
else |
503
|
|
|
{ |
504
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Validating submitted form returns: (0)"; |
505
|
|
|
return 0; |
506
|
|
|
} |
507
|
|
|
} |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
|
511
|
|
|
|
512
|
|
|
//////////////////////////////// |
513
|
|
|
// |
514
|
|
|
// PRIVATE METHODS |
515
|
|
|
// |
516
|
|
|
|
517
|
|
|
/** @private **/ |
518
|
|
|
function display_captcha($onlyTheImage=FALSE) |
519
|
|
|
{ |
520
|
|
|
$this->make_captcha(); |
521
|
|
|
$is = getimagesize($this->get_filename()); |
522
|
|
|
if($onlyTheImage) return "\n".'<img class="captchapict" src="'.$this->get_filename_url().'" '.$is[3].' alt="This is a captcha-picture. It is used to prevent mass-access by robots. (see: www.captcha.net)" title="">'."\n"; |
523
|
|
|
else return $this->public_key_input()."\n".'<img class="captchapict" src="'.$this->get_filename_url().'" '.$is[3].' alt="This is a captcha-picture. It is used to prevent mass-access by robots. (see: www.captcha.net)" title="">'."\n"; |
524
|
|
|
} |
525
|
|
|
|
526
|
|
|
/** @private **/ |
527
|
|
|
function public_key_input() |
528
|
|
|
{ |
529
|
|
|
return '<input type="hidden" name="public_key" value="'.$this->public_key.'">'; |
530
|
|
|
} |
531
|
|
|
|
532
|
|
|
/** @private **/ |
533
|
|
|
function make_captcha() |
534
|
|
|
{ |
535
|
|
|
$private_key = $this->generate_private(); |
536
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Generate private key: ($private_key)"; |
537
|
|
|
|
538
|
|
|
// create Image and set the apropriate function depending on GD-Version & websafecolor-value |
539
|
|
|
if($this->gd_version >= 2 && !$this->websafecolors) |
540
|
|
|
{ |
541
|
|
|
$func1 = 'imagecreatetruecolor'; |
542
|
|
|
$func2 = 'imagecolorallocate'; |
543
|
|
|
} |
544
|
|
|
else |
545
|
|
|
{ |
546
|
|
|
$func1 = 'imageCreate'; |
547
|
|
|
$func2 = 'imagecolorclosest'; |
548
|
|
|
} |
549
|
|
|
$image = $func1($this->lx,$this->ly); |
550
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Generate ImageStream with: ($func1())"; |
551
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: For colordefinitions we use: ($func2())"; |
552
|
|
|
|
553
|
|
|
|
554
|
|
|
// Set Backgroundcolor |
555
|
|
|
$this->random_color(224, 255); |
556
|
|
|
$back = @imagecolorallocate($image, $this->r, $this->g, $this->b); |
557
|
|
|
@ImageFilledRectangle($image,0,0,$this->lx,$this->ly,$back); |
558
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: We allocate one color for Background: (".$this->r."-".$this->g."-".$this->b.")"; |
559
|
|
|
|
560
|
|
|
// allocates the 216 websafe color palette to the image |
561
|
|
|
if($this->gd_version < 2 || $this->websafecolors) $this->makeWebsafeColors($image); |
562
|
|
|
|
563
|
|
|
|
564
|
|
|
// fill with noise or grid |
565
|
|
|
if($this->nb_noise > 0) |
566
|
|
|
{ |
567
|
|
|
// random characters in background with random position, angle, color |
568
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Fill background with noise: (".$this->nb_noise.")"; |
569
|
|
|
for($i=0; $i < $this->nb_noise; $i++) |
570
|
|
|
{ |
571
|
|
|
srand((double)microtime()*1000000); |
572
|
|
|
$size = intval(rand((int)($this->minsize / 2.3), (int)($this->maxsize / 1.7))); |
573
|
|
|
srand((double)microtime()*1000000); |
574
|
|
|
$angle = intval(rand(0, 360)); |
575
|
|
|
srand((double)microtime()*1000000); |
576
|
|
|
$x = intval(rand(0, $this->lx)); |
577
|
|
|
srand((double)microtime()*1000000); |
578
|
|
|
$y = intval(rand(0, (int)($this->ly - ($size / 5)))); |
579
|
|
|
$this->random_color(160, 224); |
580
|
|
|
$color = $func2($image, $this->r, $this->g, $this->b); |
581
|
|
|
srand((double)microtime()*1000000); |
582
|
|
|
$text = chr(intval(rand(45,250))); |
583
|
|
|
@ImageTTFText($image, $size, $angle, $x, $y, $color, $this->change_TTF(), $text); |
584
|
|
|
} |
585
|
|
|
} |
586
|
|
|
else |
587
|
|
|
{ |
588
|
|
|
// generate grid |
589
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Fill background with x-gridlines: (".(int)($this->lx / (int)($this->minsize / 1.5)).")"; |
590
|
|
View Code Duplication |
for($i=0; $i < $this->lx; $i += (int)($this->minsize / 1.5)) |
591
|
|
|
{ |
592
|
|
|
$this->random_color(160, 224); |
593
|
|
|
$color = $func2($image, $this->r, $this->g, $this->b); |
594
|
|
|
@imageline($image, $i, 0, $i, $this->ly, $color); |
595
|
|
|
} |
596
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Fill background with y-gridlines: (".(int)($this->ly / (int)(($this->minsize / 1.8))).")"; |
597
|
|
View Code Duplication |
for($i=0 ; $i < $this->ly; $i += (int)($this->minsize / 1.8)) |
598
|
|
|
{ |
599
|
|
|
$this->random_color(160, 224); |
600
|
|
|
$color = $func2($image, $this->r, $this->g, $this->b); |
601
|
|
|
@imageline($image, 0, $i, $this->lx, $i, $color); |
602
|
|
|
} |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
// generate Text |
606
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Fill forground with chars and shadows: (".$this->chars.")"; |
607
|
|
|
for($i=0, $x = intval(rand($this->minsize,$this->maxsize)); $i < $this->chars; $i++) |
608
|
|
|
{ |
609
|
|
|
$text = strtoupper(substr($private_key, $i, 1)); |
610
|
|
|
srand((double)microtime()*1000000); |
611
|
|
|
$angle = intval(rand(($this->maxrotation * -1), $this->maxrotation)); |
612
|
|
|
srand((double)microtime()*1000000); |
613
|
|
|
$size = intval(rand($this->minsize, $this->maxsize)); |
614
|
|
|
srand((double)microtime()*1000000); |
615
|
|
|
$y = intval(rand((int)($size * 1.5), (int)($this->ly - ($size / 7)))); |
616
|
|
|
$this->random_color(0, 127); |
617
|
|
|
$color = $func2($image, $this->r, $this->g, $this->b); |
618
|
|
|
$this->random_color(0, 127); |
619
|
|
|
$shadow = $func2($image, $this->r + 127, $this->g + 127, $this->b + 127); |
620
|
|
|
@ImageTTFText($image, $size, $angle, $x + (int)($size / 15), $y, $shadow, $this->change_TTF(), $text); |
621
|
|
|
@ImageTTFText($image, $size, $angle, $x, $y - (int)($size / 15), $color, $this->TTF_file, $text); |
622
|
|
|
$x += (int)($size + ($this->minsize / 5)); |
623
|
|
|
} |
624
|
|
|
@ImageJPEG($image, $this->get_filename(), $this->jpegquality); |
625
|
|
|
$res = file_exists($this->get_filename()); |
626
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Safe Image with quality [".$this->jpegquality."] as (".$this->get_filename().") returns: (".($res ? 'TRUE' : 'FALSE').")"; |
627
|
|
|
@ImageDestroy($image); |
628
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Destroy Imagestream."; |
629
|
|
|
if(!$res) die('Unable to safe captcha-image.'); |
|
|
|
|
630
|
|
|
} |
631
|
|
|
|
632
|
|
|
/** @private **/ |
633
|
|
|
function makeWebsafeColors(&$image) |
634
|
|
|
{ |
635
|
|
|
//$a = array(); |
636
|
|
|
for($r = 0; $r <= 255; $r += 51) |
637
|
|
|
{ |
638
|
|
|
for($g = 0; $g <= 255; $g += 51) |
639
|
|
|
{ |
640
|
|
|
for($b = 0; $b <= 255; $b += 51) |
641
|
|
|
{ |
642
|
|
|
$color = imagecolorallocate($image, $r, $g, $b); |
|
|
|
|
643
|
|
|
//$a[$color] = array('r'=>$r,'g'=>$g,'b'=>$b); |
644
|
|
|
} |
645
|
|
|
} |
646
|
|
|
} |
647
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Allocate 216 websafe colors to image: (".imagecolorstotal($image).")"; |
648
|
|
|
//return $a; |
649
|
|
|
} |
650
|
|
|
|
651
|
|
|
/** @private **/ |
652
|
|
|
function random_color($min,$max) |
653
|
|
|
{ |
654
|
|
|
srand((double)microtime() * 1000000); |
655
|
|
|
$this->r = intval(rand($min,$max)); |
656
|
|
|
srand((double)microtime() * 1000000); |
657
|
|
|
$this->g = intval(rand($min,$max)); |
658
|
|
|
srand((double)microtime() * 1000000); |
659
|
|
|
$this->b = intval(rand($min,$max)); |
660
|
|
|
//echo " (".$this->r."-".$this->g."-".$this->b.") "; |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
/** @private **/ |
664
|
|
|
function change_TTF() |
665
|
|
|
{ |
666
|
|
|
if(is_array($this->TTF_RANGE)) |
667
|
|
|
{ |
668
|
|
|
srand((float)microtime() * 10000000); |
669
|
|
|
$key = array_rand($this->TTF_RANGE); |
670
|
|
|
$this->TTF_file = $this->TTF_folder.$this->TTF_RANGE[$key]; |
671
|
|
|
} |
672
|
|
|
else |
673
|
|
|
{ |
674
|
|
|
$this->TTF_file = $this->TTF_folder.$this->TTF_RANGE; |
675
|
|
|
} |
676
|
|
|
return $this->TTF_file; |
677
|
|
|
} |
678
|
|
|
|
679
|
|
|
/** @private **/ |
680
|
|
|
function check_captcha($public,$private) |
681
|
|
|
{ |
682
|
|
|
if(!isset(self::$validated[$private])) { |
683
|
|
|
$res = 'FALSE'; |
684
|
|
|
// when check, destroy picture on disk |
685
|
|
|
if(file_exists($this->get_filename($public))) |
686
|
|
|
{ |
687
|
|
|
$res = @unlink($this->get_filename($public)) ? 'TRUE' : 'FALSE'; |
688
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Delete image (".$this->get_filename($public).") returns: ($res)"; |
689
|
|
|
|
690
|
|
|
$res = (strtolower($private)==strtolower($this->generate_private($public))) ? 'TRUE' : 'FALSE'; |
691
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Comparing public with private key returns: ($res)"; |
692
|
|
|
|
693
|
|
|
} else { |
694
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: Expired"; |
695
|
|
|
} |
696
|
|
|
self::$validated[$private] = ($res == 'TRUE' ? TRUE : FALSE); |
697
|
|
|
} |
698
|
|
|
|
699
|
|
|
if($this->debug) echo "\n<br>-Captcha-Debug: returning validation result (".self::$validated[$private].")"; |
700
|
|
|
return self::$validated[$private]; |
701
|
|
|
} |
702
|
|
|
|
703
|
|
|
/** @private **/ |
704
|
|
|
function get_filename($public="") |
705
|
|
|
{ |
706
|
|
|
if($public=="") $public=$this->public_key; |
707
|
|
|
return $this->tempfolder.$public.".jpg"; |
708
|
|
|
} |
709
|
|
|
|
710
|
|
|
/** @private **/ |
711
|
|
|
function get_filename_url($public="") |
|
|
|
|
712
|
|
|
{ |
713
|
|
|
if($public=="") $public = $this->public_key; |
714
|
|
|
return str_replace($_SERVER['DOCUMENT_ROOT'],'',$this->tempfolder).$public.".jpg"; |
715
|
|
|
} |
716
|
|
|
|
717
|
|
|
/** @private **/ |
718
|
|
|
function get_try($in=TRUE) |
|
|
|
|
719
|
|
|
{ |
720
|
|
|
$s = array(); |
721
|
|
|
for($i = 1; $i <= $this->maxtry; $i++) $s[$i] = $i; |
722
|
|
|
|
723
|
|
|
if($in) |
724
|
|
|
{ |
725
|
|
|
return (int)substr(strip_tags($_POST['hncaptcha']),($this->secretposition -1),1); |
726
|
|
|
} |
727
|
|
|
else |
728
|
|
|
{ |
729
|
|
|
$a = ""; |
730
|
|
|
$b = ""; |
731
|
|
View Code Duplication |
for($i = 1; $i < $this->secretposition; $i++) |
732
|
|
|
{ |
733
|
|
|
srand((double)microtime()*1000000); |
734
|
|
|
$a .= $s[intval(rand(1,$this->maxtry))]; |
735
|
|
|
} |
736
|
|
View Code Duplication |
for($i = 0; $i < (32 - $this->secretposition); $i++) |
737
|
|
|
{ |
738
|
|
|
srand((double)microtime()*1000000); |
739
|
|
|
$b .= $s[intval(rand(1,$this->maxtry))]; |
740
|
|
|
} |
741
|
|
|
return $a.$this->current_try.$b; |
742
|
|
|
} |
743
|
|
|
} |
744
|
|
|
|
745
|
|
|
/** @private **/ |
746
|
|
|
function get_gd_version() |
747
|
|
|
{ |
748
|
|
|
static $gd_version_number = null; |
749
|
|
|
if($gd_version_number === null) |
750
|
|
|
{ |
751
|
|
|
if (extension_loaded('gd')) |
752
|
|
|
{ |
753
|
|
|
$gd_version_number = 2; |
754
|
|
|
} else { |
755
|
|
|
$gd_version_number = 0; |
756
|
|
|
} |
757
|
|
|
} |
758
|
|
|
return $gd_version_number; |
759
|
|
|
} |
760
|
|
|
|
761
|
|
|
/** @private **/ |
762
|
|
|
function generate_private($public="") |
763
|
|
|
{ |
764
|
|
|
if($public=="") $public = $this->public_key; |
765
|
|
|
$key = substr(md5($this->key.$public), 16 - $this->chars / 2, $this->chars); |
766
|
|
|
return $key; |
767
|
|
|
} |
768
|
|
|
|
769
|
|
|
/** |
770
|
|
|
* |
771
|
|
|
* @shortdesc returns a message if the form validation has failed |
772
|
|
|
* @private |
773
|
|
|
* @type string |
774
|
|
|
* @return string message or blankline as placeholder |
775
|
|
|
* |
776
|
|
|
**/ |
777
|
|
|
function notvalid_msg() |
778
|
|
|
{ |
779
|
|
|
// blank line for all languages |
780
|
|
|
if($this->current_try == 1) return ' <br> '; |
781
|
|
|
|
782
|
|
|
// invalid try's: en |
783
|
|
|
if($this->lang == "en" && $this->current_try > 2 && $this->refreshlink) return 'No valid entry. Please try again:<br>Tipp: If you cannot identify the chars, you can generate a new image!'; |
784
|
|
|
if($this->lang == "en" && $this->current_try >= 2) return 'No valid entry. Please try again:<br> '; |
785
|
|
|
|
786
|
|
|
// invalid try's: de |
787
|
|
|
if($this->lang == "de" && $this->current_try > 2 && $this->refreshlink) return 'Die Eingabe war nicht korrekt.<br>Tipp: Wenn Du die Zeichen nicht erkennen kannst, generiere neue mit dem Link unten!'; |
788
|
|
|
if($this->lang == "de" && $this->current_try >= 2) return 'Die Eingabe war nicht korrekt. Bitte noch einmal versuchen:<br> '; |
789
|
|
|
|
790
|
|
|
} |
791
|
|
|
|
792
|
|
|
|
793
|
|
|
} // END CLASS hn_CAPTCHA |
794
|
|
|
|
Adding a
@return
annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.Please refer to the PHP core documentation on constructors.