Issues (287)

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.

RoboFile.php (4 issues)

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 View Code Duplication
if ( ! function_exists('glob_recursive'))
0 ignored issues
show
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...
3
{
4
	// Does not support flag GLOB_BRACE
5
	function glob_recursive($pattern, $flags = 0)
0 ignored issues
show
The function glob_recursive() has been defined more than once; this definition is ignored, only the first definition in build/update_header_comments.php (L15-25) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
6
	{
7
		$files = glob($pattern, $flags);
8
9
		foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir)
10
		{
11
			$files = array_merge($files, glob_recursive($dir.'/'.basename($pattern), $flags));
12
		}
13
14
		return $files;
15
	}
16
}
17
18
/**
19
 * This is project's console commands configuration for Robo task runner.
20
 *
21
 * @see http://robo.li/
22
 */
23
class RoboFile extends \Robo\Tasks {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
24
25
	/**
26
	 * Directories used by analysis tools
27
	 *
28
	 * @var array
29
	 */
30
	protected $taskDirs = [
31
		'build/logs',
32
		'build/pdepend',
33
		'build/phpdox',
34
	];
35
36
	/**
37
	 * Directories to remove with the clean task
38
	 *
39
	 * @var array
40
	 */
41
	protected $cleanDirs = [
42
		'coverage',
43
		'docs',
44
		'phpdoc',
45
		'build/logs',
46
		'build/phpdox',
47
		'build/pdepend'
48
	];
49
50
51
	/**
52
	 * Do static analysis tasks
53
	 */
54
	public function analyze()
55
	{
56
		$this->prepare();
57
		$this->lint();
58
		$this->phploc(TRUE);
59
		$this->phpcs(TRUE);
60
		$this->dependencyReport();
61
		$this->phpcpdReport();
62
	}
63
64
	/**
65
	 * Run all tests, generate coverage, generate docs, generate code statistics
66
	 */
67
	public function build()
68
	{
69
		$this->analyze();
70
		$this->coverage();
71
		$this->docs();
72
	}
73
74
	/**
75
	 * Cleanup temporary files
76
	 */
77
	public function clean()
78
	{
79
		$cleanFiles = [
80
			'build/humbug.json',
81
			'build/humbug-log.txt',
82
		];
83
		array_map(function ($file) {
84
			@unlink($file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
85
		}, $cleanFiles);
86
87
		// So the task doesn't complain,
88
		// make any 'missing' dirs to cleanup
89
		array_map(function ($dir) {
90
			if ( ! is_dir($dir))
91
			{
92
				`mkdir -p {$dir}`;
93
			}
94
		}, $this->cleanDirs);
95
96
		$this->_cleanDir($this->cleanDirs);
97
		$this->_deleteDir($this->cleanDirs);
98
	}
99
100
	/**
101
	 * Run unit tests and generate coverage reports
102
	 */
103
	public function coverage()
104
	{
105
		$this->taskPhpUnit()
106
			->configFile('build/phpunit.xml')
107
			->printed(true)
108
			->run();
109
	}
110
111
	/**
112
	 * Generate documentation with phpdox
113
	 */
114
	public function docs()
115
	{
116
		$cmd_parts = [
117
			'cd build',
118
			'../vendor/bin/phpdox',
119
			'cd ..'
120
		];
121
		$this->_run($cmd_parts, ' && ');
122
	}
123
124
	/**
125
	 * Verify that source files are valid
126
	 */
127
	public function lint()
128
	{
129
		$files = $this->getAllSourceFiles();
130
131
		$chunks = array_chunk($files, 6);
132
133
		foreach($chunks as $chunk)
134
		{
135
			$this->parallelLint($chunk);
136
		}
137
	}
138
139
140
	/**
141
	 * Run mutation tests with humbug
142
	 *
143
	 * @param bool $stats - if true, generates stats rather than running mutation tests
144
	 */
145
	public function mutate($stats = FALSE)
146
	{
147
		$test_parts = [
148
			'vendor/bin/humbug'
149
		];
150
151
		$stat_parts = [
152
			'vendor/bin/humbug',
153
			'--skip-killed=yes',
154
			'-v',
155
			'./build/humbug.json'
156
		];
157
158
		$cmd_parts = ($stats) ? $stat_parts : $test_parts;
159
		$this->_run($cmd_parts);
160
	}
161
162
	/**
163
	 * Run the phpcs tool
164
	 *
165
	 * @param bool $report - if true, generates reports instead of direct output
166
	 */
167
	public function phpcs($report = FALSE)
168
	{
169
		$report_cmd_parts = [
170
			'vendor/bin/phpcs',
171
			'--standard=./build/phpcs.xml',
172
			'--report-checkstyle=./build/logs/phpcs.xml',
173
		];
174
175
		$normal_cmd_parts = [
176
			'vendor/bin/phpcs',
177
			'--standard=./build/phpcs.xml',
178
		];
179
180
		$cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
181
182
		$this->_run($cmd_parts);
183
	}
184
185
	/**
186
	 * Run the phploc tool
187
	 *
188
	 * @param bool $report - if true, generates reports instead of direct output
189
	 */
190
	public function phploc($report = FALSE)
191
	{
192
		// Command for generating reports
193
		$report_cmd_parts = [
194
			'vendor/bin/phploc',
195
			'--count-tests',
196
			'--log-csv=build/logs/phploc.csv',
197
			'--log-xml=build/logs/phploc.xml',
198
			'src',
199
			'tests'
200
		];
201
202
		// Command for generating direct output
203
		$normal_cmd_parts = [
204
			'vendor/bin/phploc',
205
			'--count-tests',
206
			'src',
207
			'tests'
208
		];
209
210
		$cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
211
212
		$this->_run($cmd_parts);
213
	}
214
215
	/**
216
	 * Create temporary directories
217
	 */
218
	public function prepare()
219
	{
220
		array_map([$this, '_mkdir'], $this->taskDirs);
221
	}
222
223
	/**
224
	 * Lint php files and run unit tests
225
	 */
226
	public function test()
227
	{
228
		$this->lint();
229
		$this->taskPHPUnit()
230
			->configFile('phpunit.xml')
231
			->printed(true)
232
			->run();
233
	}
234
235
	/**
236
	 * Watches for file updates, and automatically runs appropriate actions
237
	 */
238
	public function watch()
239
	{
240
		$this->taskWatch()
241
			->monitor('composer.json', function() {
242
				$this->taskComposerUpdate()->run();
243
			})
244
			->monitor('src', function () {
245
				$this->taskExec('test')->run();
246
			})
247
			->monitor('tests', function () {
248
				$this->taskExec('test')->run();
249
			})
250
			->run();
251
	}
252
253
	/**
254
	 * Create pdepend reports
255
	 */
256
	protected function dependencyReport()
257
	{
258
		$cmd_parts = [
259
			'vendor/bin/pdepend',
260
			'--jdepend-xml=build/logs/jdepend.xml',
261
			'--jdepend-chart=build/pdepend/dependencies.svg',
262
			'--overview-pyramid=build/pdepend/overview-pyramid.svg',
263
			'src'
264
		];
265
		$this->_run($cmd_parts);
266
	}
267
268
	/**
269
	 * Get the total list of source files, including tests
270
	 *
271
	 * @return array
272
	 */
273
	protected function getAllSourceFiles()
274
	{
275
		$files = array_merge(
276
			glob_recursive('build/*.php'),
277
			glob_recursive('src/*.php'),
278
			glob_recursive('tests/*.php'),
279
			glob('*.php')
280
		);
281
282
		sort($files);
283
284
		return $files;
285
	}
286
287
	/**
288
	 * Run php's linter in one parallel task for the passed chunk
289
	 *
290
	 * @param array $chunk
291
	 */
292
	protected function parallelLint(array $chunk)
293
	{
294
		$task = $this->taskParallelExec()
295
			->timeout(5)
296
			->printed(FALSE);
297
298
		foreach($chunk as $file)
299
		{
300
			$task = $task->process("php -l {$file}");
301
		}
302
303
		$task->run();
304
	}
305
306
	/**
307
	 * Generate copy paste detector report
308
	 */
309
	protected function phpcpdReport()
310
	{
311
		$cmd_parts = [
312
			'vendor/bin/phpcpd',
313
			'--log-pmd build/logs/pmd-cpd.xml',
314
			'src'
315
		];
316
		$this->_run($cmd_parts);
317
	}
318
319
	/**
320
	 * Shortcut for joining an array of command arguments
321
	 * and then running it
322
	 *
323
	 * @param array $cmd_parts - command arguments
324
	 * @param string $join_on - what to join the command arguments with
325
	 */
326
	protected function _run(array $cmd_parts, $join_on = ' ')
327
	{
328
		$this->taskExec(implode($join_on, $cmd_parts))->run();
329
	}
330
}