XoopsCaptchaImageHandler::drawRectangles()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7

Duplication

Lines 7
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 7
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Image Creation script
4
 *
5
 * D.J.
6
 */
7
8
include dirname(dirname(dirname(dirname(dirname(__DIR__))))) . '/mainfile.php';
9
error_reporting(0);
10
$xoopsLogger->activated = false;
11
12
if (empty(Request::getString('HTTP_REFERER', '', 'SERVER')) || !preg_match('/^' . preg_quote(XOOPS_URL, '/') . '/', Request::getString('HTTP_REFERER', '', 'SERVER'))) {
13
    exit();
14
}
15
16
/**
17
 * Class XoopsCaptchaImageHandler
18
 */
19
class XoopsCaptchaImageHandler
20
{
21
    public $config = [];
22
    //var $mode = "gd"; // GD or bmp
23
    public $code;
24
    public $invalid = false;
25
26
    public $font;
27
    public $spacing;
28
    public $width;
29
    public $height;
30
31
    /**
32
     * XoopsCaptchaImageHandler constructor.
33
     */
34
    public function __construct()
35
    {
36
        if (empty($_SESSION['XoopsCaptcha_name'])) {
37
            $this->invalid = true;
38
        }
39
40 View Code Duplication
        if (!extension_loaded('gd')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
41
            $this->mode = 'bmp';
0 ignored issues
show
Bug introduced by
The property mode 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...
42
        } else {
43
            $required_functions = [
44
                'imagecreatetruecolor',
45
                'imagecolorallocate',
46
                'imagefilledrectangle',
47
                'imagejpeg',
48
                'imagedestroy',
49
                'imageftbbox'
50
            ];
51
            foreach ($required_functions as $func) {
52
                if (!function_exists($func)) {
53
                    $this->mode = 'bmp';
54
                    break;
55
                }
56
            }
57
        }
58
    }
59
60
    /**
61
     * Loading configs from CAPTCHA class
62
     * @param array $config
63
     */
64
    public function setConfig($config = [])
65
    {
66
        // Loading default preferences
67
        $this->config = $config;
68
    }
69
70
    public function loadImage()
71
    {
72
        $this->createCode();
73
        $this->setCode();
74
        $this->createImage();
75
    }
76
77
    /**
78
     * Create Code
79
     */
80
    public function createCode()
81
    {
82
        if ($this->invalid) {
83
            return;
84
        }
85
86
        if ('bmp' === $this->mode) {
87
            $this->config['num_chars'] = 4;
88
            $this->code                = mt_rand(pow(10, $this->config['num_chars'] - 1), (int)str_pad('9', $this->config['num_chars'], '9'));
89
        } else {
90
            $this->code = substr(md5(uniqid(mt_rand(), 1)), 0, $this->config['num_chars']);
91
            if (!$this->config['casesensitive']) {
92
                $this->code = strtoupper($this->code);
93
            }
94
        }
95
    }
96
97
    public function setCode()
98
    {
99
        if ($this->invalid) {
100
            return;
101
        }
102
103
        $_SESSION['XoopsCaptcha_sessioncode'] = (string)$this->code;
104
        $maxAttempts                          = (int)(@$_SESSION['XoopsCaptcha_maxattempts']);
105
106
        // Increase the attempt records on refresh
107
        if (!empty($maxAttempts)) {
108
            $_SESSION['XoopsCaptcha_attempt_' . $_SESSION['XoopsCaptcha_name']]++;
109
            if ($_SESSION['XoopsCaptcha_attempt_' . $_SESSION['XoopsCaptcha_name']] > $maxAttempts) {
110
                $this->invalid = true;
111
            }
112
        }
113
    }
114
115
    /**
116
     * @param  string $file
117
     * @return string|void
118
     */
119
    public function createImage($file = '')
0 ignored issues
show
Unused Code introduced by
The parameter $file is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
120
    {
121
        if ($this->invalid) {
122
            header('Content-type: image/gif');
123
            readfile(XOOPS_ROOT_PATH . '/images/subject/icon2.gif');
124
125
            return;
126
        }
127
128
        if ('bmp' === $this->mode) {
129
            return $this->createImageBmp();
130
        } else {
131
            return $this->createImageGd();
132
        }
133
    }
134
135
    /**
136
     *  Create CAPTCHA iamge with GD
137
     *  Originated from DuGris' SecurityImage
138
     * @param string $file
139
     */
140
    //  --------------------------------------------------------------------------- //
141
    // Class: SecurityImage 1.5                                                    //
142
    // Author: DuGris aka L. Jen <http://www.dugris.info>                           //
143
    // Email: [email protected]                                                    //
144
    // Licence: GNU                                                                 //
145
    // Project: XOOPS Project                                                   //
146
    //  --------------------------------------------------------------------------- //
147
    public function createImageGd($file = '')
148
    {
149
        $this->loadFont();
150
        $this->setImageSize();
151
152
        $this->oImage = imagecreatetruecolor($this->width, $this->height);
0 ignored issues
show
Bug introduced by
The property oImage 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...
153
        $background   = imagecolorallocate($this->oImage, 255, 255, 255);
154
        imagefilledrectangle($this->oImage, 0, 0, $this->width, $this->height, $background);
155
156
        switch ($this->config['background_type']) {
157
            default:
158
            case 0:
159
                $this->drawBars();
160
                break;
161
162
            case 1:
163
                $this->drawCircles();
164
                break;
165
166
            case 2:
167
                $this->drawLines();
168
                break;
169
170
            case 3:
171
                $this->drawRectangles();
172
                break;
173
174
            case 4:
175
                $this->drawEllipses();
176
                break;
177
178
            case 5:
179
                $this->drawPolygons();
180
                break;
181
182
            case 100:
183
                $this->createFromFile();
184
                break;
185
        }
186
        $this->drawBorder();
187
        $this->drawCode();
188
189
        if (empty($file)) {
190
            header('Content-type: image/jpeg');
191
            imagejpeg($this->oImage);
192
        } else {
193
            imagejpeg($this->oImage, XOOPS_ROOT_PATH . '/' . $this->config['imagepath'] . '/' . $file . '.jpg');
194
        }
195
        imagedestroy($this->oImage);
196
    }
197
198
    /**
199
     * @param         $name
200
     * @param  string $extension
201
     * @return array
202
     */
203
    public function _getList($name, $extension = '')
204
    {
205
        $items = [];
206
        /*
207
         if (@ require_once XOOPS_ROOT_PATH."/Frameworks/art/functions.ini.php") {
208
         load_functions("cache");
209
         if ($items = mod_loadCacheFile("captcha_{$name}", "captcha")) {
210
         return $items;
211
         }
212
         }
213
         */
214
        require_once XOOPS_ROOT_PATH . '/class/xoopslists.php';
215
        $file_path = $this->config['rootpath'] . "/{$name}";
216
        $files     = XoopsLists::getFileListAsArray($file_path);
217
        foreach ($files as $item) {
218
            if (empty($extension) || preg_match("/(\.{$extension})$/i", $item)) {
219
                $items[] = $item;
220
            }
221
        }
222
        if (function_exists('mod_createCacheFile')) {
223
            mod_createCacheFile($items, "captcha_{$name}", 'captcha');
224
        }
225
226
        return $items;
227
    }
228
229
    public function loadFont()
230
    {
231
        $fonts      = $this->_getList('fonts', 'ttf');
232
        $this->font = $this->config['rootpath'] . '/fonts/' . $fonts[array_rand($fonts)];
233
    }
234
235
    public function setImageSize()
236
    {
237
        $MaxCharWidth  = 0;
238
        $MaxCharHeight = 0;
239
        $oImage        = imagecreatetruecolor(100, 100);
240
        $text_color    = imagecolorallocate($oImage, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
0 ignored issues
show
Unused Code introduced by
$text_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...
241
        $FontSize      = $this->config['fontsize_max'];
242
        for ($Angle = -30; $Angle <= 30; ++$Angle) {
243
            for ($i = 65; $i <= 90; ++$i) {
244
                $CharDetails   = imageftbbox($FontSize, $Angle, $this->font, chr($i), []);
245
                $_MaxCharWidth = abs($CharDetails[0] + $CharDetails[2]);
246
                if ($_MaxCharWidth > $MaxCharWidth) {
247
                    $MaxCharWidth = $_MaxCharWidth;
248
                }
249
                $_MaxCharHeight = abs($CharDetails[1] + $CharDetails[5]);
250
                if ($_MaxCharHeight > $MaxCharHeight) {
251
                    $MaxCharHeight = $_MaxCharHeight;
252
                }
253
            }
254
        }
255
        imagedestroy($oImage);
256
257
        $this->height  = $MaxCharHeight + 2;
258
        $this->spacing = (int)(($this->config['num_chars'] * $MaxCharWidth) / $this->config['num_chars']);
259
        $this->width   = ($this->config['num_chars'] * $MaxCharWidth) + ($this->spacing / 2);
260
    }
261
262
    /**
263
     * Return random background
264
     *
265
     * @return null|string
266
     */
267
    public function loadBackground()
268
    {
269
        $RandBackground = null;
270
        if ($backgrounds = $this->_getList('backgrounds', '(gif|jpg|png)')) {
271
            $RandBackground = $this->config['rootpath'] . '/backgrounds/' . $backgrounds[array_rand($backgrounds)];
272
        }
273
274
        return $RandBackground;
275
    }
276
277
    /**
278
     * Draw Image background
279
     */
280
    public function createFromFile()
281
    {
282
        if ($RandImage = $this->loadBackground()) {
283
            $ImageType = @getimagesize($RandImage);
284
            switch (@$ImageType[2]) {
285
                case 1:
286
                    $BackgroundImage = imagecreatefromgif($RandImage);
287
                    break;
288
289
                case 2:
290
                    $BackgroundImage = imagecreatefromjpeg($RandImage);
291
                    break;
292
293
                case 3:
294
                    $BackgroundImage = imagecreatefrompng($RandImage);
295
                    break;
296
            }
297
        }
298
        if (!empty($BackgroundImage)) {
299
            imagecopyresized($this->oImage, $BackgroundImage, 0, 0, 0, 0, imagesx($this->oImage), imagesy($this->oImage), imagesx($BackgroundImage), imagesy($BackgroundImage));
300
            imagedestroy($BackgroundImage);
301
        } else {
302
            $this->drawBars();
303
        }
304
    }
305
306
    /**
307
     * Draw Code
308
     */
309
    public function drawCode()
310
    {
311
        for ($i = 0; $i < $this->config['num_chars']; ++$i) {
312
            // select random greyscale colour
313
            $text_color = imagecolorallocate($this->oImage, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
314
315
            // write text to image
316
            $Angle = mt_rand(10, 30);
317
            if ($i % 2) {
318
                $Angle = mt_rand(-10, -30);
319
            }
320
321
            // select random font size
322
            $FontSize = mt_rand($this->config['fontsize_min'], $this->config['fontsize_max']);
323
324
            $CharDetails = imageftbbox($FontSize, $Angle, $this->font, $this->code[$i], []);
325
            $CharHeight  = abs($CharDetails[1] + $CharDetails[5]);
326
327
            // calculate character starting coordinates
328
            $posX = ($this->spacing / 2) + ($i * $this->spacing);
329
            $posY = 2 + ($this->height / 2) + ($CharHeight / 4);
330
331
            imagefttext($this->oImage, $FontSize, $Angle, $posX, $posY, $text_color, $this->font, $this->code[$i], []);
332
        }
333
    }
334
335
    /**
336
     * Draw Border
337
     */
338
    public function drawBorder()
339
    {
340
        $rgb          = mt_rand(50, 150);
341
        $border_color = imagecolorallocate($this->oImage, $rgb, $rgb, $rgb);
342
        imagerectangle($this->oImage, 0, 0, $this->width - 1, $this->height - 1, $border_color);
343
    }
344
345
    /**
346
     * Draw Circles background
347
     */
348
    public function drawCircles()
349
    {
350
        for ($i = 1; $i <= $this->config['background_num']; ++$i) {
351
            $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
352
            imagefilledellipse($this->oImage, mt_rand(0, $this->width - 10), mt_rand(0, $this->height - 3), mt_rand(10, 20), mt_rand(20, 30), $randomcolor);
353
        }
354
    }
355
356
    /**
357
     * Draw Lines background
358
     */
359 View Code Duplication
    public function drawLines()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
360
    {
361
        for ($i = 0; $i < $this->config['background_num']; ++$i) {
362
            $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
363
            imageline($this->oImage, mt_rand(0, $this->width), mt_rand(0, $this->height), mt_rand(0, $this->width), mt_rand(0, $this->height), $randomcolor);
364
        }
365
    }
366
367
    /**
368
     * Draw Rectangles background
369
     */
370 View Code Duplication
    public function drawRectangles()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
371
    {
372
        for ($i = 1; $i <= $this->config['background_num']; ++$i) {
373
            $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
374
            imagefilledrectangle($this->oImage, mt_rand(0, $this->width), mt_rand(0, $this->height), mt_rand(0, $this->width), mt_rand(0, $this->height), $randomcolor);
375
        }
376
    }
377
378
    /**
379
     * Draw Bars background
380
     */
381
    public function drawBars()
382
    {
383 View Code Duplication
        for ($i = 0; $i <= $this->height;) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
384
            $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
385
            imageline($this->oImage, 0, $i, $this->width, $i, $randomcolor);
386
            $i += 2.5;
387
        }
388 View Code Duplication
        for ($i = 0; $i <= $this->width;) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
389
            $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
390
            imageline($this->oImage, $i, 0, $i, $this->height, $randomcolor);
391
            $i += 2.5;
392
        }
393
    }
394
395
    /**
396
     * Draw Ellipses background
397
     */
398 View Code Duplication
    public function drawEllipses()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
399
    {
400
        for ($i = 1; $i <= $this->config['background_num']; ++$i) {
401
            $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
402
            imageellipse($this->oImage, mt_rand(0, $this->width), mt_rand(0, $this->height), mt_rand(0, $this->width), mt_rand(0, $this->height), $randomcolor);
403
        }
404
    }
405
406
    /**
407
     * Draw polygons background
408
     */
409
    public function drawPolygons()
410
    {
411
        for ($i = 1; $i <= $this->config['background_num']; ++$i) {
412
            $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
413
            $coords      = [];
414
            for ($j = 1; $j <= $this->config['polygon_point']; ++$j) {
415
                $coords[] = mt_rand(0, $this->width);
416
                $coords[] = mt_rand(0, $this->height);
417
            }
418
            imagefilledpolygon($this->oImage, $coords, $this->config['polygon_point'], $randomcolor);
419
        }
420
    }
421
422
    /**
423
     *  Create CAPTCHA iamge with BMP
424
     *  TODO
425
     * @param  string $file
426
     * @return string
427
     */
428
    public function createImageBmp($file = '')
429
    {
430
        $image = '';
431
432
        if (empty($file)) {
433
            header('Content-type: image/bmp');
434
            echo $image;
435
        } else {
436
            return $image;
437
        }
438
    }
439
}
440
441
$config       = @include __DIR__ . '/../config.php';
442
$imageHandler = new \XoopsCaptchaImageHandler();
443
$imageHandler->setConfig($config);
444
$imageHandler->loadImage();
445