Issues (569)

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.

src/Task/Filesystem/FlattenDir.php (2 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
3
namespace Robo\Task\Filesystem;
4
5
use Robo\Result;
6
use Robo\Exception\TaskException;
7
use Symfony\Component\Finder\Finder;
8
9
/**
10
 * Searches for files in a nested directory structure and copies them to
11
 * a target directory with or without the parent directories. The task was
12
 * inspired by [gulp-flatten](https://www.npmjs.com/package/gulp-flatten).
13
 *
14
 * Example directory structure:
15
 *
16
 * ```
17
 * └── assets
18
 *     ├── asset-library1
19
 *     │   ├── README.md
20
 *     │   └── asset-library1.min.js
21
 *     └── asset-library2
22
 *         ├── README.md
23
 *         └── asset-library2.min.js
24
 * ```
25
 *
26
 * The following code will search the `*.min.js` files and copy them
27
 * inside a new `dist` folder:
28
 *
29
 * ``` php
30
 * <?php
31
 * $this->taskFlattenDir(['assets/*.min.js' => 'dist'])->run();
32
 * // or use shortcut
33
 * $this->_flattenDir('assets/*.min.js', 'dist');
34
 * ?>
35
 * ```
36
 *
37
 * You can also define the target directory with an additional method, instead of
38
 * key/value pairs. More similar to the gulp-flatten syntax:
39
 *
40
 * ``` php
41
 * <?php
42
 * $this->taskFlattenDir(['assets/*.min.js'])
43
 *   ->to('dist')
44
 *   ->run();
45
 * ?>
46
 * ```
47
 *
48
 * You can also append parts of the parent directories to the target path. If you give
49
 * the value `1` to the `includeParents()` method, then the top parent will be appended
50
 * to the target directory resulting in a path such as `dist/assets/asset-library1.min.js`.
51
 *
52
 * If you give a negative number, such as `-1` (the same as specifying `array(0, 1)` then
53
 * the bottom parent will be appended, resulting in a path such as
54
 * `dist/asset-library1/asset-library1.min.js`.
55
 *
56
 * The top parent directory will always be starting from the relative path to the current
57
 * directory. You can override that with the `parentDir()` method. If in the above example
58
 * you would specify `assets`, then the top parent directory would be `asset-library1`.
59
 *
60
 * ``` php
61
 * <?php
62
 * $this->taskFlattenDir(['assets/*.min.js' => 'dist'])
63
 *   ->parentDir('assets')
64
 *   ->includeParents(1)
65
 *   ->run();
66
 * ?>
67
 * ```
68
 */
69
class FlattenDir extends BaseDir
70
{
71
    /**
72
     * @var int
73
     */
74
    protected $chmod = 0755;
75
76
    /**
77
     * @var int[]
78
     */
79
    protected $parents = array(0, 0);
80
81
    /**
82
     * @var string
83
     */
84
    protected $parentDir = '';
85
86
    /**
87
     * @var string
88
     */
89
    protected $to;
90
91
    /**
92
     * {@inheritdoc}
93
     */
94
    public function __construct($dirs)
95
    {
96
        parent::__construct($dirs);
97
        $this->parentDir = getcwd();
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103
    public function run()
104
    {
105
        // find the files
106
        $files = $this->findFiles($this->dirs);
107
108
        // copy the files
109
        $this->copyFiles($files);
0 ignored issues
show
It seems like $files defined by $this->findFiles($this->dirs) on line 106 can also be of type object<Robo\Result>; however, Robo\Task\Filesystem\FlattenDir::copyFiles() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
110
111
        $fileNoun = count($files) == 1 ? ' file' : ' files';
112
        $this->printTaskSuccess("Copied {count} $fileNoun to {destination}", ['count' => count($files), 'destination' => $this->to]);
113
114
        return Result::success($this);
115
    }
116
117
    /**
118
     * Sets the default folder permissions for the destination if it does not exist.
119
     *
120
     * @link http://en.wikipedia.org/wiki/Chmod
121
     * @link http://php.net/manual/en/function.mkdir.php
122
     * @link http://php.net/manual/en/function.chmod.php
123
     *
124
     * @param int $permission
125
     *
126
     * @return $this
127
     */
128
    public function dirPermissions($permission)
129
    {
130
        $this->chmod = (int) $permission;
131
132
        return $this;
133
    }
134
135
    /**
136
     * Sets the value from which direction and how much parent dirs should be included.
137
     * Accepts a positive or negative integer or an array with two integer values.
138
     *
139
     * @param int|int[] $parents
140
     *
141
     * @return $this
142
     *
143
     * @throws TaskException
144
     */
145
    public function includeParents($parents)
146
    {
147
        if (is_int($parents)) {
148
            // if an integer is given check whether it is for top or bottom parent
149
            if ($parents >= 0) {
150
                $this->parents[0] = $parents;
151
                return $this;
152
            }
153
            $this->parents[1] = 0 - $parents;
154
            return $this;
155
        }
156
157
        if (is_array($parents)) {
158
            // check if the array has two values no more, no less
159
            if (count($parents) == 2) {
160
                $this->parents = $parents;
161
                return $this;
162
            }
163
        }
164
165
        throw new TaskException($this, 'includeParents expects an integer or an array with two values');
166
    }
167
168
    /**
169
     * Sets the parent directory from which the relative parent directories will be calculated.
170
     *
171
     * @param string $dir
172
     *
173
     * @return $this
174
     */
175
    public function parentDir($dir)
176
    {
177
        if (!$this->fs->isAbsolutePath($dir)) {
178
            // attach the relative path to current working directory
179
            $dir = getcwd() . '/' . $dir;
180
        }
181
        $this->parentDir = $dir;
182
183
        return $this;
184
    }
185
186
    /**
187
     * Sets the target directory where the files will be copied to.
188
     *
189
     * @param string $target
190
     *
191
     * @return $this
192
     */
193
    public function to($target)
194
    {
195
        $this->to = rtrim($target, '/');
196
197
        return $this;
198
    }
199
200
    /**
201
     * @param array $dirs
202
     *
203
     * @return array|\Robo\Result
204
     *
205
     * @throws \Robo\Exception\TaskException
206
     */
207 View Code Duplication
    protected function findFiles($dirs)
0 ignored issues
show
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...
208
    {
209
        $files = array();
210
211
        // find the files
212
        foreach ($dirs as $k => $v) {
213
            // reset finder
214
            $finder = new Finder();
215
216
            $dir = $k;
217
            $to = $v;
218
            // check if target was given with the to() method instead of key/value pairs
219
            if (is_int($k)) {
220
                $dir = $v;
221
                if (isset($this->to)) {
222
                    $to = $this->to;
223
                } else {
224
                    throw new TaskException($this, 'target directory is not defined');
225
                }
226
            }
227
228
            try {
229
                $finder->files()->in($dir);
230
            } catch (\InvalidArgumentException $e) {
231
                // if finder cannot handle it, try with in()->name()
232
                if (strpos($dir, '/') === false) {
233
                    $dir = './' . $dir;
234
                }
235
                $parts = explode('/', $dir);
236
                $new_dir = implode('/', array_slice($parts, 0, -1));
237
                try {
238
                    $finder->files()->in($new_dir)->name(array_pop($parts));
239
                } catch (\InvalidArgumentException $e) {
240
                    return Result::fromException($this, $e);
241
                }
242
            }
243
244
            foreach ($finder as $file) {
245
                // store the absolute path as key and target as value in the files array
246
                $files[$file->getRealpath()] = $this->getTarget($file->getRealPath(), $to);
247
            }
248
            $fileNoun = count($files) == 1 ? ' file' : ' files';
249
            $this->printTaskInfo("Found {count} $fileNoun in {dir}", ['count' => count($files), 'dir' => $dir]);
250
        }
251
252
        return $files;
253
    }
254
255
    /**
256
     * @param string $file
257
     * @param string $to
258
     *
259
     * @return string
260
     */
261
    protected function getTarget($file, $to)
262
    {
263
        $target = $to . '/' . basename($file);
264
        if ($this->parents !== array(0, 0)) {
265
            // if the parent is set, create additional directories inside target
266
            // get relative path to parentDir
267
            $rel_path = $this->fs->makePathRelative(dirname($file), $this->parentDir);
268
            // get top parents and bottom parents
269
            $parts = explode('/', rtrim($rel_path, '/'));
270
            $prefix_dir = '';
271
            $prefix_dir .= ($this->parents[0] > 0 ? implode('/', array_slice($parts, 0, $this->parents[0])) . '/' : '');
272
            $prefix_dir .= ($this->parents[1] > 0 ? implode('/', array_slice($parts, (0 - $this->parents[1]), $this->parents[1])) : '');
273
            $prefix_dir = rtrim($prefix_dir, '/');
274
            $target = $to . '/' . $prefix_dir . '/' . basename($file);
275
        }
276
277
        return $target;
278
    }
279
280
    /**
281
     * @param array $files
282
     */
283
    protected function copyFiles($files)
284
    {
285
        // copy the files
286
        foreach ($files as $from => $to) {
287
            // check if target dir exists
288
            if (!is_dir(dirname($to))) {
289
                $this->fs->mkdir(dirname($to), $this->chmod);
290
            }
291
            $this->fs->copy($from, $to);
292
        }
293
    }
294
}
295