hn_captcha::generate_private()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 6
rs 10
c 0
b 0
f 0
ccs 0
cts 6
cp 0
crap 6
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
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

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.

Loading history...
291
		  *
292
		  **/
293
		function __construct($config,$secure=TRUE)
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
__construct uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
__construct uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
__construct uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
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!");
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $this->gd_version of type integer|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
Coding Style Compatibility introduced by
The method __construct() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
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.');
0 ignored issues
show
Coding Style Compatibility introduced by
The method __construct() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
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.');
0 ignored issues
show
Coding Style Compatibility introduced by
The method __construct() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
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.');
0 ignored issues
show
Coding Style Compatibility introduced by
The method __construct() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
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(
0 ignored issues
show
Bug introduced by
The property messages does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
389
				'de'=>array(
390
							'msg1'=>'Du mu�t die <b>'.$this->chars.' Zeichen</b> im Bild, (Zahlen&nbsp;von&nbsp;<b>0&nbsp;-&nbsp;9</b> und Buchstaben&nbsp;von&nbsp;<b>A&nbsp;-&nbsp;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;
0 ignored issues
show
Unused Code introduced by
$refresh is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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;
0 ignored issues
show
Documentation Bug introduced by
It seems like isset($_POST['hncaptcha']) ? $this->get_try() : 0 can also be of type string. However, the property $current_try is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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
0 ignored issues
show
Documentation introduced by
The doc-type HTML-Output could not be parsed: Unknown type name "HTML-Output" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
446
		  *
447
		  **/
448
		function display_form()
0 ignored issues
show
Coding Style introduced by
display_form uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
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.'">&nbsp;&nbsp;';
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
0 ignored issues
show
Documentation introduced by
The doc-type 0 could not be parsed: Unknown type name "0" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
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.');
0 ignored issues
show
Coding Style Compatibility introduced by
The method make_captcha() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
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);
0 ignored issues
show
Unused Code introduced by
$color is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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="")
0 ignored issues
show
Coding Style introduced by
get_filename_url uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
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)
0 ignored issues
show
Coding Style introduced by
get_try uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
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 '&nbsp;<br>&nbsp;';
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>&nbsp;';
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>&nbsp;';
789
790
		}
791
792
793
} // END CLASS hn_CAPTCHA
794