Issues (195)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

Alpha/Util/Graph/TreeGraph.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Alpha\Util\Graph;
4
5
use Alpha\Util\Logging\Logger;
6
7
/**
8
 * Maintains the geometry for a tree graph.
9
 *
10
 * @since 1.0
11
 *
12
 * @author John Collins <[email protected]>
13
 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
14
 * @copyright Copyright (c) 2018, John Collins (founder of Alpha Framework).
15
 * All rights reserved.
16
 *
17
 * <pre>
18
 * Redistribution and use in source and binary forms, with or
19
 * without modification, are permitted provided that the
20
 * following conditions are met:
21
 *
22
 * * Redistributions of source code must retain the above
23
 *   copyright notice, this list of conditions and the
24
 *   following disclaimer.
25
 * * Redistributions in binary form must reproduce the above
26
 *   copyright notice, this list of conditions and the
27
 *   following disclaimer in the documentation and/or other
28
 *   materials provided with the distribution.
29
 * * Neither the name of the Alpha Framework nor the names
30
 *   of its contributors may be used to endorse or promote
31
 *   products derived from this software without specific
32
 *   prior written permission.
33
 *
34
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
35
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
36
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
37
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
39
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
 * </pre>
48
 */
49
class TreeGraph
50
{
51
    /**
52
     * An array of nodes on the previous level.
53
     *
54
     * @var array
55
     *
56
     * @since 1.0
57
     */
58
    private $previousLevelNodes = array();
59
60
    /**
61
     * An array of nodes in this graph.
62
     *
63
     * @var array
64
     *
65
     * @since 1.0
66
     */
67
    private $nodes = array();
68
69
    /**
70
     * The root node of the graph.
71
     *
72
     * @var \Alpha\Util\Graph\GraphNode
73
     *
74
     * @since 1.0
75
     */
76
    private $root;
77
78
    /**
79
     * The amount of space between graph rows.
80
     *
81
     * @var int
82
     *
83
     * @since 1.0
84
     */
85
    private $rowSpace;
86
87
    /**
88
     * The amount of space between graph columns.
89
     *
90
     * @var int
91
     *
92
     * @since 1.0
93
     */
94
    private $colSpace;
95
96
    /**
97
     * The amount of space between graph branches.
98
     *
99
     * @var int
100
     *
101
     * @since 1.0
102
     */
103
    private $branchSpace;
104
105
    /**
106
     * Flag to track whether the chart is rendered or not.
107
     *
108
     * @var bool
109
     *
110
     * @since 1.0
111
     */
112
    private $isRendered = false;
113
114
    /**
115
     * The index of the current node in the graph we are inspecting.
116
     *
117
     * @var int
118
     *
119
     * @since 1.0
120
     */
121
    private $position = 0;
122
123
    /**
124
     * The height of the graph.
125
     *
126
     * @var int
127
     *
128
     * @since 1.0
129
     */
130
    private $height = 0;
131
132
    /**
133
     * The width of the graph.
134
     *
135
     * @var int
136
     *
137
     * @since 1.0
138
     */
139
    private $width = 0;
140
141
    /**
142
     * Trace logger.
143
     *
144
     * @var \Alpha\Util\Logging\Logger
145
     *
146
     * @since 1.0
147
     */
148
    private static $logger = null;
149
150
    /**
151
     * Constructor.
152
     *
153
     * @param int $rowSpace
154
     * @param int $colSpace
155
     * @param int $branchSpace
156
     *
157
     * @since 1.0
158
     */
159
    public function __construct($rowSpace = 40, $colSpace = 40, $branchSpace = 80)
160
    {
161
        self::$logger = new Logger('TreeGraph');
162
163
        $this->root = new GraphNode(0, 0, 0);
164
        $this->nodes[0] = $this->root;
165
        $this->rowSpace = $rowSpace;
166
        $this->colSpace = $colSpace;
167
        $this->branchSpace = $branchSpace;
168
    }
169
170
    /**
171
     * Add a new node to the graph.
172
     *
173
     * @param int    $id
174
     * @param int    $pid
175
     * @param string $message
176
     * @param int    $w
177
     * @param int    $h
178
     * @param array  $nodeColour
179
     * @param string $URL
180
     *
181
     * @since 1.0
182
     */
183
    public function add($id, $pid, $message = '', $w = 0, $h = 0, $nodeColour, $URL)
184
    {
185
        $node = new GraphNode($id, $w, $h, $message, $nodeColour, $URL);
186
187
        if (isset($this->nodes[$pid])) {
188
            $pnode = $this->nodes[$pid];
189
            $node->setParentNode($pnode);
190
            $pnode->addChild($node);
191
        } else {
192
            $pnode = $this->root;
193
            $node->setParentNode($pnode);
0 ignored issues
show
$pnode is of type object<Alpha\Util\Graph\GraphNode>, but the function expects a object<Alpha\Util\Graph\...a\Util\Graph\GraphNode>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
194
            $this->root->addChild($node);
195
        }
196
197
        $this->nodes[$id] = $node;
198
    }
199
200
    /**
201
     * Get the specified node from the graph.
202
     *
203
     * @param int    $id
204
     *
205
     * @return \Alpha\Util\Graph\GraphNode
206
     *
207
     * @since 2.0.1
208
     */
209
    public function get($id)
210
    {
211
        if (isset($this->nodes[$id])) {
212
            return $this->nodes[$id];
213
        } else {
214
            return null;
215
        }
216
    }
217
218
    /**
219
     * The first pass of the graph.
220
     *
221
     * @param \Alpha\Util\Graph\GraphNode $node
222
     * @param int                        $level
223
     *
224
     * @since 1.0
225
     */
226
    private function firstPass($node, $level)
227
    {
228
        $this->setNeighbours($node, $level);
229
230
        if ($node->childCount() == 0) {
231
            $leftSibling = $node->getLeftSibling();
232
233
            if (isset($leftSibling)) {
234
                $node->setOffset($leftSibling->getOffset()+$leftSibling->getWidth()+$this->colSpace);
235
            } else {
236
                $node->setOffset(0);
237
            }
238
        } else {
239
            $childCount = $node->childCount();
240
241
            for ($i = 0; $i < $childCount; ++$i) {
242
                $this->firstPass($node->getChildAt($i), $level+1);
243
            }
244
245
            $midPoint = $node->getChildrenCenter();
246
            $midPoint -= $node->getWidth()/2;
247
            $leftSibling = $node->getLeftSibling();
248
249
            if (isset($leftSibling)) {
250
                $node->setOffset($leftSibling->getOffset()+$leftSibling->getWidth()+$this->colSpace);
251
                $node->setModifier($node->getOffset()-$midPoint);
252
253
                $this->layout($node, $level);
254
            } else {
255
                $node->setOffset($midPoint);
256
            }
257
        }
258
259
        self::$logger->debug('Memory usage at first scan ['.((memory_get_usage(true)/1024)/1024).' MB]');
260
    }
261
262
    /**
263
     * The second pass of the graph.
264
     *
265
     * @param \Alpha\Util\Graph\GraphNode $node
266
     * @param int                        $level
267
     * @param int                        $x
268
     * @param int                        $y
269
     *
270
     * @since 1.0
271
     */
272
    private function secondPass($node, $level, $x = 0, $y = 0)
273
    {
274
        $nodeX = $node->getOffset()+$x;
275
        $nodeY = $y;
276
277
        $node->setX($nodeX);
278
        $node->setY($nodeY);
279
280
        $this->height = ($this->height > $node->getY()+$node->getWidth()) ? $this->height : $node->getY()+$node->getWidth();
281
        $this->width = ($this->width > $nodeX+$node->getWidth()) ? $this->width : $nodeX+$node->getWidth()+10;
282
283
        if ($node->childCount() > 0) {
284
            $this->secondPass($node->getChildAt(0), $level+1, $x+$node->getModifier(), $y+$node->getHeight()+$this->rowSpace);
285
        }
286
287
        $rightSibling = $node->getRightSibling();
288
289
        if (isset($rightSibling)) {
290
            $this->secondPass($rightSibling, $level, $x, $y);
291
        }
292
293
        self::$logger->debug('Memory usage at second scan ['.((memory_get_usage(true)/1024)/1024).' MB]');
294
    }
295
296
    /**
297
     * Handles the laying out of multi-branch trees.
298
     *
299
     * @param \Alpha\Util\Graph\GraphNode $node
300
     * @param int                        $level
301
     *
302
     * @since 1.0
303
     */
304
    private function layout($node, $level)
305
    {
306
        $firstChild = $node->getChildAt(0);
307
        $firstChildLeftNeighbour = $firstChild->getLeftSibling();
308
309
        for ($j = 1; $j <= $level; ++$j) {
310
            $modifierSumRight = 0;
311
            $modifierSumLeft = 0;
312
            $rightAncestor = $firstChild;
313
            $leftAncestor = $firstChildLeftNeighbour;
314
315
            for ($l = 0; $l < $j; ++$l) {
316
                $rightAncestor = $rightAncestor->getParentNode();
317
                $leftAncestor = $leftAncestor->getParentNode();
318
                $modifierSumRight += $rightAncestor->getModifier();
319
                $modifierSumLeft += $leftAncestor->getModifier();
320
            }
321
322
            $totalGap = ($firstChildLeftNeighbour->getOffset()+$modifierSumLeft+$firstChildLeftNeighbour->getWidth()+$this->branchSpace)-($firstChild->getOffset()+$modifierSumRight);
323
324
            if ($totalGap > 0) {
325
                $subTree = $node;
326
                $subTreesCount = 0;
327
328
                while (isset($subTree) && $subTree !== $leftAncestor) {
329
                    $subTree = $subTree->getLeftSibling();
330
                    ++$subTreesCount;
331
                }
332
333
                $subTreeMove = $node;
334
                $singleGap = $totalGap/$subTreesCount;
335
336
                while (isset($subTreeMove) && $subTreeMove !== $leftAncestor) {
337
                    $subTreeMove = $subTreeMove->getLeftSibling();
338
339
                    if (isset($subTreeMove)) {
340
                        $subTreeMove->setOffset($subTreeMove->getOffset()+$totalGap);
341
                        $subTreeMove->setModifier($subTreeMove->getModifier()+$totalGap);
342
                        $totalGap -= $singleGap;
343
                    }
344
                }
345
            }
346
347
            if ($firstChild->childCount() == 0) {
348
                $firstChild = $this->getLeftmost($node, 0, $j);
349
            } else {
350
                $firstChild = $firstChild->getChildAt(0);
351
            }
352
353
            if (isset($firstChild)) {
354
                $firstChildLeftNeighbour = $firstChild->getLeftSibling();
355
            }
356
        }
357
    }
358
359
    /**
360
     * Setup neighbour nodes.
361
     *
362
     * @param \Alpha\Util\Graph\GraphNode $node
363
     * @param int                        $level
364
     *
365
     * @since 1.0
366
     */
367
    private function setNeighbours($node, $level)
368
    {
369
        if (isset($this->previousLevelNodes[$level])) {
370
            $node->setLeftSibling($this->previousLevelNodes[$level]);
371
        }
372
373
        if ($node->getLeftSibling()) {
374
            $node->getLeftSibling()->setRightSibling($node);
375
        }
376
        $this->previousLevelNodes[$level] = $node;
377
    }
378
379
    /**
380
     * Get left most node in the branch.
381
     *
382
     * @param \Alpha\Util\Graph\GraphNode $node
383
     * @param int                        $level
384
     * @param int                        $maxlevel
385
     *
386
     * @return \Alpha\Util\Graph\GraphNode
387
     *
388
     * @since 1.0
389
     */
390
    private function getLeftmost($node, $level, $maxlevel)
391
    {
392
        if ($level >= $maxlevel) {
393
            return $node;
394
        }
395
396
        $childCount = $node->childCount();
397
398
        if ($childCount == 0) {
399
            return;
400
        }
401
402
        for ($i = 0; $i < $childCount; ++$i) {
403
            $child = $node->getChildAt($i);
404
405
            $leftmostDescendant = $this->getLeftmost($child, $level+1, $maxlevel);
406
407
            if (isset($leftmostDescendant)) {
408
                return $leftmostDescendant;
409
            }
410
        }
411
412
        return;
413
    }
414
415
    /**
416
     * Render the chart in memory.
417
     *
418
     * @since 1.0
419
     */
420
    protected function render()
421
    {
422
        $this->firstPass($this->root, 0);
423
        $this->secondPass($this->root, 0);
424
425
        foreach ($this->nodes as $node) {
426
            $node->setUpLinks();
427
        }
428
429
        $this->isRendered = true;
430
    }
431
432
    /**
433
     * Get the width of the graph, will invoke render() if not already rendered.
434
     *
435
     * @since 1.0
436
     */
437
    public function getWidth()
438
    {
439
        if (!$this->isRendered) {
440
            $this->render();
441
        }
442
443
        return $this->width;
444
    }
445
446
    /**
447
     * Get the heith of the graph, will invoke render() if not already rendered.
448
     *
449
     * @since 1.0
450
     */
451
    public function getHeight()
452
    {
453
        if (!$this->isRendered) {
454
            $this->render();
455
        }
456
457
        return $this->height;
458
    }
459
460
    /**
461
     * Get the next GraphNode instance in the graph, will invoke render() if not already rendered.
462
     *
463
     * @return \Alpha\Util\Graph\GraphNode
464
     *
465
     * @since 1.0
466
     */
467
    public function next()
468
    {
469
        if (!$this->isRendered) {
470
            $this->render();
471
        }
472
473
        if (isset($this->nodes[$this->position+1])) {
474
            ++$this->position;
475
476
            return $this->nodes[$this->position];
477
        } else {
478
            return;
479
        }
480
    }
481
482
    /**
483
     * Check to see if another GraphNode instance in the graph is available.
484
     *
485
     * @return bool
486
     *
487
     * @since 1.0
488
     */
489
    public function hasNext()
490
    {
491
        if (isset($this->nodes[$this->position+1])) {
492
            return true;
493
        } else {
494
            return false;
495
        }
496
    }
497
}
498