Issues (11)

Security Analysis    no request data  

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/Util/Output.php (1 issue)

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 League\CLImate\Util;
4
5
use League\CLImate\Exceptions\InvalidArgumentException;
6
use League\CLImate\Exceptions\UnexpectedValueException;
7
use League\CLImate\Util\Writer\WriterInterface;
8
9
class Output
10
{
11
    /**
12
     * The content to be output
13
     *
14
     * @var string $content
15
     */
16
    protected $content;
17
18
    /**
19
     * Whether or not to add a new line after the output
20
     *
21
     * @var boolean $new_line
22
     */
23
    protected $new_line = true;
24
25
    /**
26
     * The array of available writers
27
     *
28
     * @var array[] $writers
29
     */
30
    protected $writers = [];
31
32
    /**
33
     * Default writers when one isn't specifed
34
     *
35
     * @var WriterInterface[] $default
36
     */
37
    protected $default = [];
38
39
    /**
40
     * Writers to be used just once
41
     *
42
     * @var null|array $once
43
     */
44
    protected $once;
45
46 972
    protected $persist = false;
47
48 972
    public function __construct()
49 972
    {
50 972
        $this->add('out', new Writer\StdOut);
51
        $this->add('error', new Writer\StdErr);
52 972
        $this->add('buffer', new Writer\Buffer);
53 972
54
        $this->defaultTo('out');
55
    }
56
57
    /**
58 40
     * Dictate that a new line should not be added after the output
59
     */
60 40
    public function sameLine()
61
    {
62 40
        $this->new_line = false;
63
64
        return $this;
65
    }
66
67
    /**
68
     * Add a writer to the available writers
69
     *
70
     * @param string $key
71
     * @param WriterInterface|array $writer
72
     *
73 972
     * @return \League\CLImate\Util\Output
74
     */
75 972
    public function add($key, $writer)
76
    {
77 972
        $this->writers[$key] = $this->resolve(Helper::toArray($writer));
0 ignored issues
show
It seems like $writer defined by parameter $writer on line 75 can also be of type object<League\CLImate\Ut...Writer\WriterInterface>; however, League\CLImate\Util\Helper::toArray() does only seem to accept string|array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
78
79
        return $this;
80
    }
81
82
    /**
83
     * Set the default writer
84
     *
85 972
     * @param string|array $keys
86
     */
87 972
    public function defaultTo($keys)
88 972
    {
89
        $this->default = $this->getWriters($keys);
90
    }
91
92
    /**
93
     * Add a default writer
94
     *
95 4
     * @param string|array $keys
96
     */
97 4
    public function addDefault($keys)
98 4
    {
99
        $this->default = array_merge($this->default, $this->getWriters($keys));
100
    }
101
102
    /**
103
     * Register a writer to be used just once
104
     *
105
     * @param string|array $keys
106
     *
107 8
     * @return \League\CLImate\Util\Output
108
     */
109 8
    public function once($keys)
110
    {
111 8
        $this->once = $this->getWriters($keys);
112
113
        return $this;
114
    }
115
116
    /**
117
     * Persist or un-persist one time writers (for multi-line output)
118
     *
119
     * @param bool $persist
120
     *
121 4
     * @return \League\CLImate\Util\Output
122
     */
123 4
    public function persist($persist = true)
124
    {
125 4
        $this->persist = (bool) $persist;
126 4
127 4
        if (!$this->persist) {
128
            $this->resetOneTimers();
129 4
        }
130
131
        return $this;
132
    }
133
134
    /**
135
     * Get a specific writer
136
     *
137
     * @param string $writer
138
     *
139
     * @return WriterInterface|array
140 4
     * @throws UnexpectedValueException if writer key doesn't exist
141
     */
142 4
    public function get($writer)
143
    {
144
        if (!array_key_exists($writer, $this->writers)) {
145
            throw new UnexpectedValueException('Unknown writer [' . $writer . ']');
146 4
        }
147 4
148
        if (count($this->writers[$writer]) == 1) {
149
            return reset($this->writers[$writer]);
150
        }
151
152
        return $this->writers[$writer];
153
    }
154
155
    /**
156
     * Get the currently available writers
157
     *
158 4
     * @return array
159
     */
160 4
    public function getAvailable()
161
    {
162 4
        $writers = [];
163 4
164 4
        foreach ($this->writers as $key => $writer) {
165
            $writers[$key] = $this->getReadable($writer);
166 4
        }
167
168
        return $writers;
169
    }
170
171
    /**
172
     * Write the content using the provided writer
173
     *
174 80
     * @param  string $content
175
     */
176 80
    public function write($content)
177 40
    {
178 40
        if ($this->new_line) {
179
            $content .= PHP_EOL;
180 80
        }
181 80
182 68
        foreach ($this->getCurrentWriters() as $writer) {
183
            $writer->write($content);
184 68
        }
185 68
186
        $this->resetOneTimers();
187
    }
188
189
    /**
190
     * Resolve the writer(s) down to an array of WriterInterface classes
191
     *
192
     * @param WriterInterface|array|string $writer
193
     *
194 972
     * @return array
195
     */
196 972
    protected function resolve($writer)
197
    {
198 972
        $resolver = 'resolve' . ucwords(gettype($writer)) . 'Writer';
199 972
200
        if (method_exists($this, $resolver) && $resolved = $this->{$resolver}($writer)) {
201
            return $resolved;
202 8
        }
203
204
        $this->handleUnknownWriter($writer);
205
    }
206
207
    /**
208
     * @param array $writer
209
     *
210 972
     * @return array
211
     */
212 972
    protected function resolveArrayWriter($writer)
213
    {
214
        return Helper::flatten(array_map([$this, 'resolve'], $writer));
215
    }
216
217
    /**
218
     * @param object $writer
219
     *
220 972
     * @return WriterInterface|false
221
     */
222 972
    protected function resolveObjectWriter($writer)
223 972
    {
224
        if ($writer instanceof WriterInterface) {
225
            return $writer;
226 4
        }
227
228
        return false;
229
    }
230
231
    /**
232
     * @param string $writer
233
     *
234 12
     * @return array|false
235
     */
236 12
    protected function resolveStringWriter($writer)
237 8
    {
238
        if (is_string($writer) && array_key_exists($writer, $this->writers)) {
239
            return $this->writers[$writer];
240 4
        }
241
242
        return false;
243
    }
244
245
    /**
246
     * @param mixed $writer
247 8
     * @throws InvalidArgumentException For non-valid writer
248
     */
249
    protected function handleUnknownWriter($writer)
250
    {
251 8
        // If we've gotten this far and don't know what it is,
252 4
        // let's at least try and give a helpful error message
253 4
        if (is_object($writer)) {
254
            throw new InvalidArgumentException('Class [' . get_class($writer) . '] must implement '
255
                                    . 'League\CLImate\Util\Writer\WriterInterface.');
256
        }
257 4
258
        // No idea, just tell them we can't resolve it
259
        throw new InvalidArgumentException('Unable to resolve writer [' . $writer . ']');
260
    }
261
262
    /**
263
     * Get the readable version of the writer(s)
264
     *
265
     * @param array $writer
266
     *
267 4
     * @return string|array
268
     */
269 4
    protected function getReadable(array $writer)
270
    {
271 4
        $classes = array_map('get_class', $writer);
272 4
273
        if (count($classes) == 1) {
274
            return reset($classes);
275 4
        }
276
277
        return $classes;
278
    }
279
280
    /**
281
     * Get the writers based on their keys
282
     *
283
     * @param string|array $keys
284
     *
285 972
     * @return array
286
     */
287 972
    protected function getWriters($keys)
288
    {
289 972
        $writers = array_flip(Helper::toArray($keys));
290
291
        return Helper::flatten(array_intersect_key($this->writers, $writers));
292
    }
293
294
    /**
295 80
     * @return WriterInterface[]
296
     */
297 80
    protected function getCurrentWriters()
298
    {
299
        return $this->once ?: $this->default;
300
    }
301
302
    /**
303 68
     * Reset anything only used for the current content being written
304
     */
305
    protected function resetOneTimers()
306 68
    {
307
        // Reset new line flag for next time
308 68
        $this->new_line = true;
309
310 68
        if (!$this->persist) {
311 68
            // Reset once since we only want to use it... once.
312 68
            $this->once = null;
313
        }
314
    }
315
}
316