This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
5 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
6 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||
7 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||
8 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||
9 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||
10 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
11 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||
12 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
13 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||
14 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
15 | * |
||
16 | * This software consists of voluntary contributions made by many individuals |
||
17 | * and is licensed under the LGPL. For more information please see |
||
18 | * <http://phing.info>. |
||
19 | */ |
||
20 | |||
21 | namespace Phing\Task\Ext\Analyzer\Pdepend; |
||
22 | |||
23 | use PDepend\Application; |
||
24 | use PDepend\Util\Log; |
||
25 | use Phing\Exception\BuildException; |
||
26 | use Phing\Io\File; |
||
27 | use Phing\Task; |
||
28 | use Phing\Type\Element\FileSetAware; |
||
29 | use Phing\Util\StringHelper; |
||
30 | |||
31 | /** |
||
32 | * Runs the PHP_Depend software analyzer and metric tool. |
||
33 | * Performs static code analysis on a given source base. |
||
34 | * |
||
35 | * @package phing.tasks.ext.pdepend |
||
36 | * @author Benjamin Schultz <[email protected]> |
||
37 | * @since 2.4.1 |
||
38 | */ |
||
39 | class PhpDependTask extends Task |
||
40 | { |
||
41 | use FileSetAware; |
||
42 | |||
43 | /** |
||
44 | * A php source code filename or directory |
||
45 | * |
||
46 | * @var File |
||
47 | */ |
||
48 | protected $file = null; |
||
49 | |||
50 | /** |
||
51 | * List of allowed file extensions. Default file extensions are <b>php</b> |
||
52 | * and <p>php5</b>. |
||
53 | * |
||
54 | * @var array<string> |
||
55 | */ |
||
56 | protected $allowedFileExtensions = ['php', 'php5']; |
||
57 | |||
58 | /** |
||
59 | * List of exclude directories. Default exclude dirs are <b>.git</b>, |
||
60 | * <b>.svn</b> and <b>CVS</b>. |
||
61 | * |
||
62 | * @var array<string> |
||
63 | */ |
||
64 | protected $excludeDirectories = ['.git', '.svn', 'CVS']; |
||
65 | |||
66 | /** |
||
67 | * List of exclude packages |
||
68 | * |
||
69 | * @var array<string> |
||
70 | */ |
||
71 | protected $excludePackages = []; |
||
72 | |||
73 | /** |
||
74 | * Should the parse ignore doc comment annotations? |
||
75 | * |
||
76 | * @var boolean |
||
77 | */ |
||
78 | protected $withoutAnnotations = false; |
||
79 | |||
80 | /** |
||
81 | * Should PHP_Depend treat <b>+global</b> as a regular project package? |
||
82 | * |
||
83 | * @var boolean |
||
84 | */ |
||
85 | protected $supportBadDocumentation = false; |
||
86 | |||
87 | /** |
||
88 | * Flag for enable/disable debugging |
||
89 | * |
||
90 | * @var boolean |
||
91 | */ |
||
92 | protected $debug = false; |
||
93 | |||
94 | /** |
||
95 | * PHP_Depend configuration file |
||
96 | * |
||
97 | * @var File |
||
98 | */ |
||
99 | protected $configFile = null; |
||
100 | |||
101 | /** |
||
102 | * Logger elements |
||
103 | * |
||
104 | * @var PhpDependLoggerElement[] |
||
105 | */ |
||
106 | protected $loggers = []; |
||
107 | |||
108 | /** |
||
109 | * Analyzer elements |
||
110 | * |
||
111 | * @var PhpDependAnalyzerElement[] |
||
112 | */ |
||
113 | protected $analyzers = []; |
||
114 | |||
115 | /** |
||
116 | * Flag that determines whether to halt on error |
||
117 | * |
||
118 | * @var boolean |
||
119 | */ |
||
120 | protected $haltonerror = false; |
||
121 | |||
122 | /** |
||
123 | * @var bool |
||
124 | */ |
||
125 | private $oldVersion = false; |
||
126 | |||
127 | /** |
||
128 | * @var string |
||
129 | */ |
||
130 | protected $pharLocation = ""; |
||
131 | |||
132 | /** |
||
133 | * Load the necessary environment for running PHP_Depend |
||
134 | * |
||
135 | * @throws BuildException |
||
136 | */ |
||
137 | 2 | protected function requireDependencies() |
|
138 | { |
||
139 | 2 | if (!empty($this->pharLocation)) { |
|
140 | // nasty but necessary: reorder the autoloaders so the one in the PHAR gets priority |
||
141 | $autoloadFunctions = spl_autoload_functions(); |
||
142 | $composerAutoloader = null; |
||
143 | if (get_class($autoloadFunctions[0][0]) === 'Composer\Autoload\ClassLoader') { |
||
144 | $composerAutoloader = $autoloadFunctions[0]; |
||
145 | spl_autoload_unregister($composerAutoloader); |
||
146 | } |
||
147 | |||
148 | $GLOBALS['_SERVER']['SCRIPT_NAME'] = '-'; |
||
149 | ob_start(); |
||
150 | include_once 'phar://' . $this->pharLocation . '/vendor/autoload.php'; |
||
151 | ob_end_clean(); |
||
152 | |||
153 | if ($composerAutoloader !== null) { |
||
154 | spl_autoload_register($composerAutoloader); |
||
155 | } |
||
156 | } |
||
157 | |||
158 | // check 2.x version (composer/phar) |
||
159 | 2 | if (class_exists('PDepend\\TextUI\\Runner')) { |
|
160 | 2 | return; |
|
161 | } |
||
162 | |||
163 | throw new BuildException("This task requires PDepend 2.x", $this->getLocation()); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Set the input source file or directory |
||
168 | * |
||
169 | * @param File $file The input source file or directory |
||
170 | */ |
||
171 | public function setFile(File $file) |
||
172 | { |
||
173 | $this->file = $file; |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * Sets a list of filename extensions for valid php source code files |
||
178 | * |
||
179 | * @param string $fileExtensions List of valid file extensions |
||
180 | */ |
||
181 | public function setAllowedFileExtensions($fileExtensions) |
||
182 | { |
||
183 | $this->allowedFileExtensions = []; |
||
184 | |||
185 | $token = ' ,;'; |
||
186 | $ext = strtok($fileExtensions, $token); |
||
187 | |||
188 | while ($ext !== false) { |
||
189 | $this->allowedFileExtensions[] = $ext; |
||
190 | $ext = strtok($token); |
||
191 | } |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * Sets a list of exclude directories |
||
196 | * |
||
197 | * @param string $excludeDirectories List of exclude directories |
||
198 | */ |
||
199 | public function setExcludeDirectories($excludeDirectories) |
||
200 | { |
||
201 | $this->excludeDirectories = []; |
||
202 | |||
203 | $token = ' ,;'; |
||
204 | $pattern = strtok($excludeDirectories, $token); |
||
205 | |||
206 | while ($pattern !== false) { |
||
207 | $this->excludeDirectories[] = $pattern; |
||
208 | $pattern = strtok($token); |
||
209 | } |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Sets a list of exclude packages |
||
214 | * |
||
215 | * @param string $excludePackages Exclude packages |
||
216 | */ |
||
217 | public function setExcludePackages($excludePackages) |
||
218 | { |
||
219 | $this->excludePackages = []; |
||
220 | |||
221 | $token = ' ,;'; |
||
222 | $pattern = strtok($excludePackages, $token); |
||
223 | |||
224 | while ($pattern !== false) { |
||
225 | $this->excludePackages[] = $pattern; |
||
226 | $pattern = strtok($token); |
||
227 | } |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * Should the parser ignore doc comment annotations? |
||
232 | * |
||
233 | * @param boolean $withoutAnnotations |
||
234 | */ |
||
235 | public function setWithoutAnnotations($withoutAnnotations) |
||
236 | { |
||
237 | $this->withoutAnnotations = StringHelper::booleanValue($withoutAnnotations); |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * Should PHP_Depend support projects with a bad documentation. If this |
||
242 | * option is set to <b>true</b>, PHP_Depend will treat the default package |
||
243 | * <b>+global</b> as a regular project package. |
||
244 | * |
||
245 | * @param boolean $supportBadDocumentation |
||
246 | */ |
||
247 | public function setSupportBadDocumentation($supportBadDocumentation) |
||
248 | { |
||
249 | $this->supportBadDocumentation = StringHelper::booleanValue($supportBadDocumentation); |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * Set debugging On/Off |
||
254 | * |
||
255 | * @param boolean $debug |
||
256 | */ |
||
257 | public function setDebug($debug) |
||
258 | { |
||
259 | $this->debug = StringHelper::booleanValue($debug); |
||
260 | } |
||
261 | |||
262 | /** |
||
263 | * Set halt on error |
||
264 | * |
||
265 | * @param boolean $haltonerror |
||
266 | */ |
||
267 | public function setHaltonerror($haltonerror) |
||
268 | { |
||
269 | $this->haltonerror = StringHelper::booleanValue($haltonerror); |
||
270 | } |
||
271 | |||
272 | /** |
||
273 | * Set the configuration file |
||
274 | * |
||
275 | * @param File $configFile The configuration file |
||
276 | */ |
||
277 | public function setConfigFile(File $configFile) |
||
278 | { |
||
279 | $this->configFile = $configFile; |
||
280 | } |
||
281 | |||
282 | /** |
||
283 | * Create object for nested logger element |
||
284 | * |
||
285 | * @return PhpDependLoggerElement |
||
286 | */ |
||
287 | 2 | public function createLogger() |
|
288 | { |
||
289 | 2 | $num = array_push($this->loggers, new PhpDependLoggerElement()); |
|
290 | |||
291 | 2 | return $this->loggers[$num - 1]; |
|
292 | } |
||
293 | |||
294 | /** |
||
295 | * Create object for nested analyzer element |
||
296 | * |
||
297 | * @return PhpDependAnalyzerElement |
||
298 | */ |
||
299 | 1 | public function createAnalyzer() |
|
300 | { |
||
301 | 1 | $num = array_push($this->analyzers, new PhpDependAnalyzerElement()); |
|
302 | |||
303 | 1 | return $this->analyzers[$num - 1]; |
|
304 | } |
||
305 | |||
306 | /** |
||
307 | * @param string $pharLocation |
||
308 | */ |
||
309 | public function setPharLocation($pharLocation) |
||
310 | { |
||
311 | $this->pharLocation = $pharLocation; |
||
312 | } |
||
313 | |||
314 | /** |
||
315 | * Executes PHP_Depend_TextUI_Runner against PhingFile or a FileSet |
||
316 | * |
||
317 | * @throws BuildException |
||
318 | */ |
||
319 | 2 | public function main() |
|
320 | { |
||
321 | 2 | $this->requireDependencies(); |
|
322 | |||
323 | 2 | if (!isset($this->file) and count($this->filesets) == 0) { |
|
324 | throw new BuildException('Missing either a nested fileset or attribute "file" set'); |
||
325 | } |
||
326 | |||
327 | 2 | if (count($this->loggers) == 0) { |
|
328 | throw new BuildException('Missing nested "logger" element'); |
||
329 | } |
||
330 | |||
331 | 2 | $this->validateLoggers(); |
|
332 | 2 | $this->validateAnalyzers(); |
|
333 | |||
334 | 2 | $filesToParse = $this->getFilesToParse(); |
|
335 | |||
336 | 2 | $runner = $this->createRunner(); |
|
337 | 2 | $runner->setSourceArguments($filesToParse); |
|
338 | |||
339 | 2 | foreach ($this->loggers as $logger) { |
|
340 | // Register logger |
||
341 | 2 | if ($this->oldVersion) { |
|
342 | $runner->addLogger( |
||
343 | $logger->getType(), |
||
344 | $logger->getOutfile()->__toString() |
||
345 | ); |
||
346 | } else { |
||
347 | 2 | $runner->addReportGenerator( |
|
348 | 2 | $logger->getType(), |
|
349 | 2 | $logger->getOutfile()->__toString() |
|
350 | 2 | ); |
|
351 | } |
||
352 | } |
||
353 | |||
354 | 2 | foreach ($this->analyzers as $analyzer) { |
|
355 | // Register additional analyzer |
||
356 | 1 | $runner->addOption( |
|
357 | 1 | $analyzer->getType(), |
|
358 | 1 | $analyzer->getValue() |
|
359 | 1 | ); |
|
360 | } |
||
361 | |||
362 | // Disable annotation parsing |
||
363 | 2 | if ($this->withoutAnnotations) { |
|
364 | $runner->setWithoutAnnotations(); |
||
365 | } |
||
366 | |||
367 | // Enable bad documentation support |
||
368 | 2 | if ($this->supportBadDocumentation) { |
|
369 | $runner->setSupportBadDocumentation(); |
||
370 | } |
||
371 | |||
372 | // Check for suffix |
||
373 | 2 | if (count($this->allowedFileExtensions) > 0) { |
|
374 | 2 | $runner->setFileExtensions($this->allowedFileExtensions); |
|
375 | } |
||
376 | |||
377 | // Check for ignore directories |
||
378 | 2 | if (count($this->excludeDirectories) > 0) { |
|
379 | 2 | $runner->setExcludeDirectories($this->excludeDirectories); |
|
380 | } |
||
381 | |||
382 | // Check for exclude packages |
||
383 | 2 | if (count($this->excludePackages) > 0) { |
|
384 | $runner->setExcludePackages($this->excludePackages); |
||
385 | } |
||
386 | |||
387 | 2 | $runner->run(); |
|
388 | |||
389 | 2 | if ($runner->hasParseErrors() === true) { |
|
390 | $this->log('Following errors occurred:'); |
||
391 | |||
392 | foreach ($runner->getParseErrors() as $error) { |
||
393 | $this->log($error); |
||
394 | } |
||
395 | |||
396 | if ($this->haltonerror === true) { |
||
397 | throw new BuildException('Errors occurred during parse process'); |
||
398 | } |
||
399 | } |
||
400 | } |
||
401 | |||
402 | /** |
||
403 | * Validates the available loggers |
||
404 | * |
||
405 | * @throws BuildException |
||
406 | */ |
||
407 | 2 | protected function validateLoggers() |
|
408 | { |
||
409 | 2 | foreach ($this->loggers as $logger) { |
|
410 | 2 | if ($logger->getType() === '') { |
|
411 | throw new BuildException('Logger missing required "type" attribute'); |
||
412 | } |
||
413 | |||
414 | 2 | if ($logger->getOutfile() === null) { |
|
415 | throw new BuildException('Logger requires "outfile" attribute'); |
||
416 | } |
||
417 | } |
||
418 | } |
||
419 | |||
420 | /** |
||
421 | * Validates the available analyzers |
||
422 | * |
||
423 | * @throws BuildException |
||
424 | */ |
||
425 | 2 | protected function validateAnalyzers() |
|
426 | { |
||
427 | 2 | foreach ($this->analyzers as $analyzer) { |
|
428 | 1 | if ($analyzer->getType() === '') { |
|
429 | throw new BuildException('Analyzer missing required "type" attribute'); |
||
430 | } |
||
431 | |||
432 | 1 | if (count($analyzer->getValue()) === 0) { |
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
433 | throw new BuildException('Analyzer missing required "value" attribute'); |
||
434 | } |
||
435 | } |
||
436 | } |
||
437 | |||
438 | /** |
||
439 | * @return array |
||
440 | */ |
||
441 | 2 | private function getFilesToParse() |
|
442 | { |
||
443 | 2 | $filesToParse = []; |
|
444 | |||
445 | 2 | if ($this->file instanceof File) { |
|
446 | $filesToParse[] = $this->file->__toString(); |
||
447 | return $filesToParse; |
||
448 | } |
||
449 | |||
450 | // append any files in filesets |
||
451 | 2 | foreach ($this->filesets as $fs) { |
|
452 | 2 | $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); |
|
453 | |||
454 | 2 | foreach ($files as $filename) { |
|
455 | 2 | $f = new File($fs->getDir($this->project), $filename); |
|
456 | 2 | $filesToParse[] = $f->getAbsolutePath(); |
|
457 | } |
||
458 | } |
||
459 | 2 | return $filesToParse; |
|
460 | } |
||
461 | |||
462 | /** |
||
463 | * @return object |
||
464 | */ |
||
465 | 2 | private function createRunner() |
|
466 | { |
||
467 | 2 | $application = new Application(); |
|
468 | |||
469 | 2 | if (!empty($this->configFile)) { |
|
470 | if (file_exists($this->configFile->__toString()) === false) { |
||
471 | throw new BuildException( |
||
472 | 'The configuration file "' . $this->configFile->__toString() . '" doesn\'t exist.' |
||
473 | ); |
||
474 | } |
||
475 | |||
476 | $application->setConfigurationFile($this->configFile); |
||
477 | } |
||
478 | |||
479 | 2 | $runner = $application->getRunner(); |
|
480 | |||
481 | 2 | if ($this->debug) { |
|
482 | // Enable debug logging |
||
483 | Log::setSeverity(1); |
||
484 | } |
||
485 | |||
486 | 2 | return $runner; |
|
487 | } |
||
488 | } |
||
489 |