GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( d61e75...15dc0f )
by Maurice
10:32 queued 05:16
created

src/Naneau/Obfuscator/Node/Visitor/ScrambleUse.php (2 issues)

Labels
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
 * ScrambleUse.php
4
 *
5
 * @category        Naneau
6
 * @package         Obfuscator
7
 * @subpackage      NodeVisitor
8
 */
9
10
namespace Naneau\Obfuscator\Node\Visitor;
11
12
use Naneau\Obfuscator\Node\Visitor\TrackingRenamerTrait;
13
use Naneau\Obfuscator\Node\Visitor\SkipTrait;
14
15
use Naneau\Obfuscator\Node\Visitor\Scrambler as ScramblerVisitor;
16
17
use PhpParser\Node;
18
19
use PhpParser\Node\Name;
20
use PhpParser\Node\Name\FullyQualified;
21
22
use PhpParser\Node\Param;
23
24
use PhpParser\Node\Stmt\Class_ as ClassStatement;
25
use PhpParser\Node\Stmt\Use_ as UseStatement;
26
use PhpParser\Node\Stmt\UseUse as UseUseStatement;
27
use PhpParser\Node\Stmt\StaticVar;
28
29
use PhpParser\Node\Expr\ClassConstFetch;
30
use PhpParser\Node\Expr\StaticCall;
31
use PhpParser\Node\Expr\StaticPropertyFetch;
32
use PhpParser\Node\Expr\New_ as NewExpression;
33
use PhpParser\Node\Expr\Instanceof_ as InstanceOfExpression;
34
35
use PhpParser\Node\Expr\Variable;
36
37
/**
38
 * ScrambleUse
39
 *
40
 * @category        Naneau
41
 * @package         Obfuscator
42
 * @subpackage      NodeVisitor
43
 */
44
class ScrambleUse extends ScramblerVisitor
45
{
46
    use TrackingRenamerTrait;
47
    use SkipTrait;
48
49
    /**
50
     * Active class
51
     *
52
     * @var ClassStatement|bool
53
     **/
54
    private $classNode;
55
56
    /**
57
     * Before node traversal
58
     *
59
     * @param  Node[] $nodes
60
     * @return array
61
     **/
62
    public function beforeTraverse(array $nodes)
63
    {
64
        // Reset renamed list
65
        $this->resetRenamed();
66
67
        // Find the class node
68
        $this->classNode = $this->findClass($nodes);
69
70
        // Scan for use statements
71
        $this->scanUse($nodes);
72
73
        return $nodes;
74
    }
75
76
    /**
77
     * Check all variable nodes
78
     *
79
     * @param  Node $node
80
     * @return void
81
     **/
82
    public function enterNode(Node $node)
83
    {
84
        // Class statements
85
        if ($node instanceof ClassStatement) {
86
            // Classes that extend another class
87
            if ($node->extends !== null) {
88
                $extends = $node->extends->toString();
89
                if ($this->isRenamed($extends)) {
90
                    $node->extends = new Name($this->getNewName($extends));
91
                }
92
            }
93
94
            // Classes that implement an interface
95
            if ($node->implements !== null && count($node->implements) > 0) {
96
97
                $implements = array();
98
99
                foreach($node->implements as $implementsName) {
100
101
                    // Old name (as string)
102
                    $oldName = $implementsName->toString();
103
104
                    if ($this->isRenamed($oldName)) {
105
                        // If renamed, set new one
106
                        $implements[] = new Name($this->getNewName($oldName));
107
                    } else {
108
                        // If not renamed, pass old one
109
                        $implements[] = $implementsName;
110
                    }
111
                }
112
113
                $node->implements = $implements;
114
            }
115
116
            return $node;
117
        }
118
119
        // Param rename
120
        if ($node instanceof Param && $node->type instanceof Name) {
121
122
            // Name
123
            $name = $node->type->toString();
124
125
            // Has it been renamed?
126
            if ($this->isRenamed($name)) {
127
                $node->type = $this->getNewName($name);
128
                return $node;
129
            }
130
        }
131
132
        // Static call or constant lookup on class
133
        if (
134
            $node instanceof ClassConstFetch
135
            || $node instanceof StaticCall
136
            || $node instanceof StaticPropertyFetch
137
            || $node instanceof StaticVar
138
            || $node instanceof NewExpression
139
            || $node instanceof InstanceOfExpression
140
        ) {
141
142
            // We need to be in a class for this to work
143
            if (empty($this->classNode)) {
144
                return;
145
            }
146
147
            // We need a name
148
            if (!($node->class instanceof Name)) {
149
                return;
150
            }
151
152
            // Class name
153
            $name = $node->class->toString();
154
155
            if ($name === $this->classNode->name) {
156
                return;
157
            }
158
159
            // Has it been renamed?
160
            if ($this->isRenamed($name)) {
161
                $node->class = new Name($this->getNewName($name));
162
                return $node;
163
            }
164
        }
165
    }
166
167
    /**
168
     * Scramble at use statements
169
     *
170
     * @param  Node[] $nodes
171
     * @return void
172
     **/
173
    private function scanUse(array $nodes)
174
    {
175
        foreach ($nodes as $node) {
176
            // Scramble the private method definitions
177
            if ($node instanceof UseStatement) {
178
                foreach($node->uses as $useNode) {
179
180
                    // Record original name and scramble it
181
                    $originalName = $useNode->name->toString();
182
183
                    // Prefix all classes with underscores, but don't modify them further
184
                    $rename =
185
                        strpos($originalName, '_') === false
186
                        &&
187
                        count($useNode->name->parts) > 1;
188
189
                    if (!$rename) {
190
                        $useNode->name = new Name(
191
                            '\\' . $useNode->name
192
                        );
193
194
                        continue;
195
                    }
196
197
                    // Scramble into new use name
198
                    $newName = $this->scrambleString(
199
                        $originalName
200
                        . '-'
201
                        . $useNode->alias
202
                    );
203
204
                    // Record renaming of full class
205
                    $this->renamed($originalName, $newName);
206
207
                    // Record renaming of alias
208
                    $this->renamed($useNode->alias, $newName);
209
210
                    // Set the new alias
211
                    $useNode->alias = $newName;
212
                }
213
            }
214
215
            // Recurse over child nodes
216
            if (isset($node->stmts) && is_array($node->stmts)) {
0 ignored issues
show
Accessing stmts on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
217
                $this->scanUse($node->stmts);
0 ignored issues
show
Accessing stmts on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
218
            }
219
        }
220
    }
221
222
    /**
223
     * Find (the first) class node in a set of nodes
224
     *
225
     * @param array $nodes
226
     * @return ClassStatement|bool returns falls if no class can be found
227
     **/
228
    private function findClass(array $nodes)
229
    {
230
        foreach($nodes as $node) {
231
            if ($node instanceof ClassStatement) {
232
                return $node;
233
            }
234
235
            if (isset($node->stmts) && is_array($node->stmts)) {
236
                $class = $this->findClass($node->stmts);
237
238
                if ($class instanceof ClassStatement) {
239
                    return $class;
240
                }
241
            }
242
        }
243
244
        return false;
245
    }
246
}
247